Показать полную графическую версию : Проверка на правильность написанных данных
Invincible
13-12-2016, 17:55
Всем привет. Можете помочь с макросом, который будет проверять каждую ячейку столбца и в том случае, если в тексте ячейки присутствует ошибка в проставлении скобок, останавливать работу макроса и выводить сообщение, в каком месте листа макрос обнаружил ошибку. Например, запись «Текст(текст)» будет правильно, а такая – «Текст)текст(» или «((( )) () ))» будут неправильными и для них следует вывести сообщение об ошибке.
1. В тексте или в формуле?
2. А такая: «(())(())»?
3. Образец документа/рабочей книги на «поиграться» в студию!
Invincible, вот примерная болванка кода, рассчитана на один тип скобок, функция проверки согласованности скобок возвращает булево значение:
Option Explicit
Sub Sample()
Debug.Print CheckBrackets("Текст(текст)")
Debug.Print CheckBrackets("Текст)текст(")
Debug.Print CheckBrackets("((( )) () ))")
Debug.Print CheckBrackets("((( )( ))( ))")
Debug.Print CheckBrackets("(()(((()))")
End Sub
Function CheckBrackets(strString As String) As Boolean
Dim i As Integer
Dim currLevel As Integer
currLevel = 0
For i = 1 To Len(strString)
Select Case Mid(strString, i, 1)
Case "("
currLevel = currLevel + 1
Case ")"
currLevel = currLevel - 1
Case Else
' Nothing to do
End Select
If currLevel < 0 Then
CheckBrackets = False
Exit Function
End If
Next
CheckBrackets = currLevel = 0
End Function
Всё прочее:
проверять каждую ячейку столбца »
останавливать работу макроса и выводить сообщение, в каком месте листа макрос обнаружил ошибку. »
— после предоставления образца документа/Рабочей книги.
Invincible
14-12-2016, 23:11
В тексте или в формуле? »
В тексте.
А такая: «(())(())»? »
Подходит, нужно чтобы на каждую открывающуюся скобку была закрывающая. Если какой-то скобки не хватает выдавать ошибку или на несоответствующую скобку.
3. Образец документа/рабочей книги на «поиграться» в студию! »
Тут лучше представить если значения вводятся в ячейку столбца, если ввели данные верно продолжается работа, если нет, то выводится ошибка.
Если какой-то скобки не хватает выдавать ошибку или на несоответствующую скобку. »
Я бы лучше выдавал сообщение Хорошо/Плохо и помечал бы ячейки с ошибкой.
Тут лучше представить если значения вводятся в ячейку столбца, если ввели данные верно продолжается работа, если нет, то выводится ошибка. »
Ну, честно говоря, не хочется привязываться к функции OnChange. Не очень Excel приспособлен для таких вещей. Как по мне, так проще «ручками» вызвать макрос по кнопке/горячей клавише. Или хотя бы по кнопке на самом Рабочем листе [Проверить согласованность введённых данных!] (саму кнопку можно исключить из вывода на печать).
Примерно такой код:
Option Explicit
Sub CheckRangeInColumnH()
Dim objErrorsRange As Range
Dim objRange As Range
Set objErrorsRange = Nothing
With ThisWorkbook.Worksheets.Item("Лист1")
For Each objRange In Intersect(.UsedRange, .Columns.Item("H"))
Select Case LCase(TypeName(objRange.Value))
Case "string"
If Not CheckBrackets(objRange.Value) Then
If objErrorsRange Is Nothing Then
objRange.Activate
Set objErrorsRange = objRange
Else
Set objErrorsRange = Union(objErrorsRange, objRange)
End If
End If
Case Else
' Nothing to do
End Select
Next
End With
If objErrorsRange Is Nothing Then
MsgBox "Ошибок не найдено", vbOKOnly + vbInformation, "Ошибок не найдено"
Else
objErrorsRange.Select
MsgBox "Найдено " & CStr(objErrorsRange.Cells.Count) & " ошибок", vbOKOnly + vbExclamation, "Найдены ошибки"
Set objErrorsRange = Nothing
End If
End Sub
Function CheckBrackets(strString As String) As Boolean
Dim i As Integer
Dim currLevel As Integer
currLevel = 0
For i = 1 To Len(strString)
Select Case Mid(strString, i, 1)
Case "("
currLevel = currLevel + 1
Case ")"
currLevel = currLevel - 1
Case Else
' Nothing to do
End Select
If currLevel < 0 Then
CheckBrackets = False
Exit Function
End If
Next
CheckBrackets = currLevel = 0
End Function
Все найденные ячейки с ошибками выделяются, и активной становится ячейка с первой найденной ошибкой (внутри выделения удобно перебирать ячейки клавишей «Tab»).
Прилагаю и саму рабочую книгу с макросом и кнопкой: 142120.
Invincible
15-12-2016, 00:17
Iska, Спасибо, буду пробовать.
Invincible, я там упростил код немного. Убедитесь, что Вы забрали именно исправленный (хотя работать будет и первый вариант).
Invincible
16-12-2016, 19:57
Iska, А можете добавить, чтобы макрос работал при переносе данных в другой столбец/лист?
Invincible, можете и сами. Вот здесь:
With ThisWorkbook.Worksheets.Item("Лист1")
— лист. Вот здесь:
For Each objRange In Intersect(.UsedRange, .Columns.Item("H"))
— столбец. Другое дело, как тогда быть с кнопкой на самом листе.
Основной вопрос — как найти в Рабочей книге данные, которые требуется обрабатывать? Как, например, определить потребный лист? Самое простое и правильное — использовать активный рабочий лист, вместо указания конкретного. Но тогда нам нужно как-то исключить из возможной обработки те листы, на которых никак не может быть потребных данных.
Тот же вопрос касается и местоположения потребных данных — как их найти на Рабочем листе, как определить их точное местоположение? Вот, Вы пишете просто «столбец», но по сути же это может быть неверным. Может присутствовать заголовок таблицы, шапка таблицы/заголовки столбцов (причём, в несколько строк), промежуточные данные, подвал/итоги таблицы, подписи и т.п. элементы. Как? Можно, скажем, зная структуру таблицы и или/содержимое шапки таблицы/заголовков столбцов, задаться некими правилами и от этого танцевать.
Что скажете?
Invincible
18-12-2016, 18:36
Iska, Можно сделать, чтобы обрабатывались только данные в которых присутствуют скобки "()"?
Я имел в виду чтобы написали данные в столбец "A" проверили их макросом, потом перенесли их в столбец "С" и макрос также среагировал как и в первом случае, затем перенесли на другой лист в любой столбец и результат работы макроса оставался тем же.
Iska, Можно сделать, чтобы обрабатывались только данные в которых присутствуют скобки "()"? »
Э… а как определить без обработки есть ли там скобки?!
Я имел в виду чтобы написали данные в столбец "A" проверили их макросом, »
Как определить, что данные именно в столбце A? А не в B, и не в C, и не в D?
потом перенесли их в столбец "С" »
Как определить, что данные именно в столбце A? А не в B, и не в C, и не в D?
затем перенесли на другой лист в любой столбец »
Как определить, что данные именно в столбце A? А не в B, и не в C, и не в D? Насчёт более раннего предложения: искомый лист == активный лист — согласны?
Invincible
18-12-2016, 21:05
искомый лист == активный лист — согласны? »
Да.
А можно тогда искомый столбец == активный столбец?
А можно тогда искомый столбец == активный столбец? »
Можно. Можно даже так: есть выделение на активном листе — проверяем только выделение, нет выделения (активна/выделена только одна ячейка) — проверяем заполненную часть столбца, содержащего эту ячейку. Поведение выделения после обработки — как в последнем макросе. Устроит?
Invincible
19-12-2016, 01:00
проверяем заполненную часть столбца, содержащего эту ячейку. »
Если у меня курсор стоит на ячейке B2, то проверка будет проходить с B2 и до конца столбца B?
Если у меня курсор стоит на ячейке B2, то проверка будет проходить с B2 и до конца столбца B? »
Нет. По дипазону, образованному пересечением заполненного диапазона листа (.UsedRange) и столбца B. Если выделено больше одной ячейки — только в пределах этого выделения.
Попробуйте так: 142208 (листы диаграммы, диалога были добавлены намеренно для иллюстрации поведения, никакой значимой ценности они не несут).
Invincible
21-12-2016, 00:53
Можно. Можно даже так: есть выделение на активном листе — проверяем только выделение, нет выделения (активна/выделена только одна ячейка) — проверяем заполненную часть столбца, содержащего эту ячейку. Поведение выделения после обработки — как в последнем макросе. Устроит? »
То есть сейчас осуществляется поиск с активного столбца?
…осуществляется поиск с активного столбца? »
Не понял.
Invincible
21-12-2016, 01:30
Не понял. »
На котором курсор стоит, я так понял из Вашей рабочей книги
Поиск в этом случае осуществляется в диапазоне, представляющем собой пересечение (Intersect()) Используемого диапазона (.UsedRange) активного Рабочего листа (.ActiveSheet) и столбца (.Columns.Item()), в котором находится активная ячейка (Selection.Column). В целом определяется вот здесь:
With .ActiveSheet ' На активном Рабочем листе
If Selection.Count = 1 Then ' Если в выделении присутствует одна ячейка…
' …то искомый диапазон находим пересечением Используемого диапазона
' активного Рабочего листа и столбца, в котором находится активная ячейка.
Set objCheckRange = Intersect(.UsedRange, .Columns.Item(Selection.Column))
Else
' …иначе — ищем в самом выделении.
Set objCheckRange = Selection
End If
If Not objCheckRange Is Nothing Then ' Если искомый диапазон не пуст…
Invincible
21-12-2016, 07:22
Iska, Но если выделена одна ячейка а поиск осуществляется по всему столбцу?
Invincible
21-12-2016, 07:48
Iska, Можно еще последнее попросить, чтобы выводилось сообщение с адресом где обнаружилось ошибка. К примеру находится ошибка в ячейке A2, после нахождения ошибки выводится MsgBox с сообщением "Обнаружена ошибка в ячейке A2", потом например ошибка в ячейке A10, выводится еще один MsgBox с сообщением "Обнаружена ошибка в ячейке A10", и в самом конце уже MsgBox с сообщением "Всего найдено 2 ошибки".
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.
Available in ZeroNet 1osznRoVratMCN3bFoFpR2pSV5c9z6sTC