PDA

Показать полную графическую версию : Проверка на правильность написанных данных


Страниц : [1] 2

Invincible
13-12-2016, 17:55
Всем привет. Можете помочь с макросом, который будет проверять каждую ячейку столбца и в том случае, если в тексте ячейки присутствует ошибка в проставлении скобок, останавливать работу макроса и выводить сообщение, в каком месте листа макрос обнаружил ошибку. Например, запись «Текст(текст)» будет правильно, а такая – «Текст)текст(» или «((( )) () ))» будут неправильными и для них следует вывести сообщение об ошибке.

Iska
13-12-2016, 19:16
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. Образец документа/рабочей книги на «поиграться» в студию! »
Тут лучше представить если значения вводятся в ячейку столбца, если ввели данные верно продолжается работа, если нет, то выводится ошибка.

Iska
15-12-2016, 00:07
Если какой-то скобки не хватает выдавать ошибку или на несоответствующую скобку. »
Я бы лучше выдавал сообщение Хорошо/Плохо и помечал бы ячейки с ошибкой.

Тут лучше представить если значения вводятся в ячейку столбца, если ввели данные верно продолжается работа, если нет, то выводится ошибка. »
Ну, честно говоря, не хочется привязываться к функции 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, Спасибо, буду пробовать.

Iska
15-12-2016, 00:22
Invincible, я там упростил код немного. Убедитесь, что Вы забрали именно исправленный (хотя работать будет и первый вариант).

Invincible
16-12-2016, 19:57
Iska, А можете добавить, чтобы макрос работал при переносе данных в другой столбец/лист?

Iska
16-12-2016, 20:25
Invincible, можете и сами. Вот здесь:
With ThisWorkbook.Worksheets.Item("Лист1")
— лист. Вот здесь:
For Each objRange In Intersect(.UsedRange, .Columns.Item("H"))
— столбец. Другое дело, как тогда быть с кнопкой на самом листе.

Основной вопрос — как найти в Рабочей книге данные, которые требуется обрабатывать? Как, например, определить потребный лист? Самое простое и правильное — использовать активный рабочий лист, вместо указания конкретного. Но тогда нам нужно как-то исключить из возможной обработки те листы, на которых никак не может быть потребных данных.

Тот же вопрос касается и местоположения потребных данных — как их найти на Рабочем листе, как определить их точное местоположение? Вот, Вы пишете просто «столбец», но по сути же это может быть неверным. Может присутствовать заголовок таблицы, шапка таблицы/заголовки столбцов (причём, в несколько строк), промежуточные данные, подвал/итоги таблицы, подписи и т.п. элементы. Как? Можно, скажем, зная структуру таблицы и или/содержимое шапки таблицы/заголовков столбцов, задаться некими правилами и от этого танцевать.

Что скажете?

Invincible
18-12-2016, 18:36
Iska, Можно сделать, чтобы обрабатывались только данные в которых присутствуют скобки "()"?
Я имел в виду чтобы написали данные в столбец "A" проверили их макросом, потом перенесли их в столбец "С" и макрос также среагировал как и в первом случае, затем перенесли на другой лист в любой столбец и результат работы макроса оставался тем же.

Iska
18-12-2016, 20:42
Iska, Можно сделать, чтобы обрабатывались только данные в которых присутствуют скобки "()"? »
Э… а как определить без обработки есть ли там скобки?!

Я имел в виду чтобы написали данные в столбец "A" проверили их макросом, »
Как определить, что данные именно в столбце A? А не в B, и не в C, и не в D?

потом перенесли их в столбец "С" »
Как определить, что данные именно в столбце A? А не в B, и не в C, и не в D?

затем перенесли на другой лист в любой столбец »
Как определить, что данные именно в столбце A? А не в B, и не в C, и не в D? Насчёт более раннего предложения: искомый лист == активный лист — согласны?

Invincible
18-12-2016, 21:05
искомый лист == активный лист — согласны? »
Да.
А можно тогда искомый столбец == активный столбец?

Iska
18-12-2016, 21:40
А можно тогда искомый столбец == активный столбец? »
Можно. Можно даже так: есть выделение на активном листе — проверяем только выделение, нет выделения (активна/выделена только одна ячейка) — проверяем заполненную часть столбца, содержащего эту ячейку. Поведение выделения после обработки — как в последнем макросе. Устроит?

Invincible
19-12-2016, 01:00
проверяем заполненную часть столбца, содержащего эту ячейку. »
Если у меня курсор стоит на ячейке B2, то проверка будет проходить с B2 и до конца столбца B?

Iska
19-12-2016, 01:26
Если у меня курсор стоит на ячейке B2, то проверка будет проходить с B2 и до конца столбца B? »
Нет. По дипазону, образованному пересечением заполненного диапазона листа (.UsedRange) и столбца B. Если выделено больше одной ячейки — только в пределах этого выделения.

Попробуйте так: 142208 (листы диаграммы, диалога были добавлены намеренно для иллюстрации поведения, никакой значимой ценности они не несут).

Invincible
21-12-2016, 00:53
Можно. Можно даже так: есть выделение на активном листе — проверяем только выделение, нет выделения (активна/выделена только одна ячейка) — проверяем заполненную часть столбца, содержащего эту ячейку. Поведение выделения после обработки — как в последнем макросе. Устроит? »
То есть сейчас осуществляется поиск с активного столбца?

Iska
21-12-2016, 01:28
…осуществляется поиск с активного столбца? »
Не понял.

Invincible
21-12-2016, 01:30
Не понял. »
На котором курсор стоит, я так понял из Вашей рабочей книги

Iska
21-12-2016, 02:39
Поиск в этом случае осуществляется в диапазоне, представляющем собой пересечение (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