Макрос Trim_By_Formula применяет функцию листа СЖПРОБЕЛЫ к ячейкам выделенного диапазона. В результате из текстовых значений ячеек удаляются все лидирующие, финиширующие пробелы. Каждый из многократно повторяющихся пробелов внутри текста ячейки заменяется на единичный пробел. Скрытые (невидимые) ячейки и ячейки, содержащие формулы, дату и время макросом игнорируются. [vba]
Код
Sub Trim_By_Formula() ' применить функцию СЖПРОБЕЛЫ к ячейкам выделенного диапазона If TypeName(Selection) <> "Range" Then Exit Sub Dim iCell As Range, rRange As Range With ActiveSheet.Cells Set rRange = Intersect(Selection, ActiveSheet.UsedRange, .SpecialCells(xlCellTypeVisible), .SpecialCells(xlCellTypeConstants)) End With If rRange Is Nothing Then Exit Sub Application.ScreenUpdating = False For Each iCell In rRange With iCell If Not IsDate(.Value) And Not .NumberFormat Like "*" & ":" & "*" Then 'если в ячейке не дата и не время .Value = Application.WorksheetFunction.Trim(.Value) End If End With Next Application.ScreenUpdating = True rRange.Select End Sub
[/vba]
Макрос Trim_By_Formula применяет функцию листа СЖПРОБЕЛЫ к ячейкам выделенного диапазона. В результате из текстовых значений ячеек удаляются все лидирующие, финиширующие пробелы. Каждый из многократно повторяющихся пробелов внутри текста ячейки заменяется на единичный пробел. Скрытые (невидимые) ячейки и ячейки, содержащие формулы, дату и время макросом игнорируются. [vba]
Код
Sub Trim_By_Formula() ' применить функцию СЖПРОБЕЛЫ к ячейкам выделенного диапазона If TypeName(Selection) <> "Range" Then Exit Sub Dim iCell As Range, rRange As Range With ActiveSheet.Cells Set rRange = Intersect(Selection, ActiveSheet.UsedRange, .SpecialCells(xlCellTypeVisible), .SpecialCells(xlCellTypeConstants)) End With If rRange Is Nothing Then Exit Sub Application.ScreenUpdating = False For Each iCell In rRange With iCell If Not IsDate(.Value) And Not .NumberFormat Like "*" & ":" & "*" Then 'если в ячейке не дата и не время .Value = Application.WorksheetFunction.Trim(.Value) End If End With Next Application.ScreenUpdating = True rRange.Select End Sub
Леш, как-то я не обращал внимания на тему... Когда-то на форуме(не помню где) я предложил такую конструкцию: [vba]
Code
Public Sub www() ActiveSheet.UsedRange.SpecialCells(2).Value = Application.Trim(ActiveSheet.UsedRange.SpecialCells(2).Value) End Sub
[/vba] Она делала для темы все как надо, однако твой тезка Казанский резонно предположил, что SpecialCells(2) может состоять из нескольких диапазонов. Тогда моя конструкция просто запортит данные. И предложил свой вариант: [vba]
Code
Sub TrimSpaces() Dim a As Range For Each a In ActiveSheet.UsedRange.SpecialCells(xlCellTypeConstants).Areas a = Application.Trim(a) Next End Sub
[/vba] Так гораздо быстрей, чем если перебирать по одной ячейке. Пример прилагаю. PS А зачем ты пропускал даты и время? Я в пример специально в А1 поставил дату-время.
Леш, как-то я не обращал внимания на тему... Когда-то на форуме(не помню где) я предложил такую конструкцию: [vba]
Code
Public Sub www() ActiveSheet.UsedRange.SpecialCells(2).Value = Application.Trim(ActiveSheet.UsedRange.SpecialCells(2).Value) End Sub
[/vba] Она делала для темы все как надо, однако твой тезка Казанский резонно предположил, что SpecialCells(2) может состоять из нескольких диапазонов. Тогда моя конструкция просто запортит данные. И предложил свой вариант: [vba]
Code
Sub TrimSpaces() Dim a As Range For Each a In ActiveSheet.UsedRange.SpecialCells(xlCellTypeConstants).Areas a = Application.Trim(a) Next End Sub
[/vba] Так гораздо быстрей, чем если перебирать по одной ячейке. Пример прилагаю. PS А зачем ты пропускал даты и время? Я в пример специально в А1 поставил дату-время.KuklP
Серёга, ты обратил внимание, когда пост был мною написан? 2 года назад. Глупый был, не опытный Сейчас макрос выглядит несколько по-другому: [vba]
Code
Sub Trim_By_Formula() ' применить функцию СЖПРОБЕЛЫ к видимым ячейкам выделенного диапазона If TypeName(Selection) <> "Range" Then Exit Sub Dim rCell As Range, rRange As Range With ActiveSheet.Cells Set rRange = Intersect(Selection, ActiveSheet.UsedRange, .SpecialCells(xlCellTypeVisible), .SpecialCells(xlCellTypeConstants)) End With If rRange Is Nothing Then Exit Sub Application.ScreenUpdating = False For Each rCell In rRange With rCell .Value = Replace(.Value, Chr(160), " ") ' заменить неразрывный пробел Chr(160) на простой .Value = Application.WorksheetFunction.Trim(.Value) ' СЖПРОБЕЛЫ .Value = Replace(.Value, " " & Chr(10), Chr(10)) ' убрать пробел перед LF .Value = Replace(.Value, Chr(10) & " ", Chr(10)) ' убрать пробел после LF End With Next rCell Application.ScreenUpdating = True rRange.Select End Sub
[/vba] я сам про этот топик уже забыл давно, поэтому и не подправил
Quote (KuklP)
А зачем ты пропускал даты и время?
Серёга, ты обратил внимание, когда пост был мною написан? 2 года назад. Глупый был, не опытный Сейчас макрос выглядит несколько по-другому: [vba]
Code
Sub Trim_By_Formula() ' применить функцию СЖПРОБЕЛЫ к видимым ячейкам выделенного диапазона If TypeName(Selection) <> "Range" Then Exit Sub Dim rCell As Range, rRange As Range With ActiveSheet.Cells Set rRange = Intersect(Selection, ActiveSheet.UsedRange, .SpecialCells(xlCellTypeVisible), .SpecialCells(xlCellTypeConstants)) End With If rRange Is Nothing Then Exit Sub Application.ScreenUpdating = False For Each rCell In rRange With rCell .Value = Replace(.Value, Chr(160), " ") ' заменить неразрывный пробел Chr(160) на простой .Value = Application.WorksheetFunction.Trim(.Value) ' СЖПРОБЕЛЫ .Value = Replace(.Value, " " & Chr(10), Chr(10)) ' убрать пробел перед LF .Value = Replace(.Value, Chr(10) & " ", Chr(10)) ' убрать пробел после LF End With Next rCell Application.ScreenUpdating = True rRange.Select End Sub
[/vba] я сам про этот топик уже забыл давно, поэтому и не подправил Alex_ST
Ну и что ты этим хотел сказать? ИМХО, это монопенисуально . Разница ровно в 1 символ по длине кода. TypeName и TypeOf я применяю рэндомно (какой первым в голову придёт). А на счёт скорости у меня данных нет. К стати, у меня на рабочем компе несколько сокращённый вариант: [vba]
Code
Sub Trim_By_Formula() ' применить функцию СЖПРОБЕЛЫ к видимым ячейкам выделенного диапазона If TypeName(Selection) <> "Range" Then Exit Sub Dim rCell As Range, rRange As Range With ActiveSheet.UsedRange Set rRange = Intersect(Selection, .SpecialCells(xlCellTypeVisible), .SpecialCells(xlCellTypeConstants)) End With If rRange Is Nothing Then Exit Sub Application.ScreenUpdating = False For Each rCell In rRange With rCell .Value = Replace(.Value, Chr(160), " ") ' Chr(160) - неразрывный пробел .Value = Application.WorksheetFunction.Trim(.Value) ' СЖПРОБЕЛЫ .Value = Replace(.Value, " " & Chr(10), Chr(10)) ' пробел перед LF .Value = Replace(.Value, Chr(10) & " ", Chr(10)) ' пробел после LF End With Next rCell Application.ScreenUpdating = True rRange.Select End Sub
[/vba] Вот если бы ты предложил RegExp вместо Replace и Application.Trim, то, наверное, было бы красиво. Я, к сожалению, RegExp так толком и не осилил. А ковыряться в чужих не совсем подходящих и переделывать их лень.
Ну и что ты этим хотел сказать? ИМХО, это монопенисуально . Разница ровно в 1 символ по длине кода. TypeName и TypeOf я применяю рэндомно (какой первым в голову придёт). А на счёт скорости у меня данных нет. К стати, у меня на рабочем компе несколько сокращённый вариант: [vba]
Code
Sub Trim_By_Formula() ' применить функцию СЖПРОБЕЛЫ к видимым ячейкам выделенного диапазона If TypeName(Selection) <> "Range" Then Exit Sub Dim rCell As Range, rRange As Range With ActiveSheet.UsedRange Set rRange = Intersect(Selection, .SpecialCells(xlCellTypeVisible), .SpecialCells(xlCellTypeConstants)) End With If rRange Is Nothing Then Exit Sub Application.ScreenUpdating = False For Each rCell In rRange With rCell .Value = Replace(.Value, Chr(160), " ") ' Chr(160) - неразрывный пробел .Value = Application.WorksheetFunction.Trim(.Value) ' СЖПРОБЕЛЫ .Value = Replace(.Value, " " & Chr(10), Chr(10)) ' пробел перед LF .Value = Replace(.Value, Chr(10) & " ", Chr(10)) ' пробел после LF End With Next rCell Application.ScreenUpdating = True rRange.Select End Sub
[/vba] Вот если бы ты предложил RegExp вместо Replace и Application.Trim, то, наверное, было бы красиво. Я, к сожалению, RegExp так толком и не осилил. А ковыряться в чужих не совсем подходящих и переделывать их лень.Alex_ST
Здорово, Серёга! Обедаем, по форумам шарим? Я тоже добрался с бутербродом в левой руке и мышкой в правой. Твой паттерн получается длиннее чем последовательное применение простых и всем понятных Replace и Application.Trim Так что, наверное, не имеет смысла и трогать уже имеющийся и многократно проверенный макрос
Здорово, Серёга! Обедаем, по форумам шарим? Я тоже добрался с бутербродом в левой руке и мышкой в правой. Твой паттерн получается длиннее чем последовательное применение простых и всем понятных Replace и Application.Trim Так что, наверное, не имеет смысла и трогать уже имеющийся и многократно проверенный макросAlex_ST
Привет Леш, Саня, все. Да вроде не длинней. И подозреваю, что работать будет быстрей. Хотя, если бы ты изменил по моему совету cells на areas, это утверждение потребовало бы доказательств:-)
Привет Леш, Саня, все. Да вроде не длинней. И подозреваю, что работать будет быстрей. Хотя, если бы ты изменил по моему совету cells на areas, это утверждение потребовало бы доказательств:-)KuklP
Ну с НДС и мы чего-то стoим! kuklp60@gmail.com WM Z206653985942, R334086032478, U238399322728
Сообщение отредактировал KuklP - Среда, 15.08.2012, 12:53
KuklP, если воспользоваться предложенной моей регой + Trim
Quote (Alex_ST)
из текстовых значений ячеек удаляются все лидирующие, финиширующие пробелы. Каждый из многократно повторяющихся пробелов внутри текста ячейки заменяется на единичный пробел.
Кстати [vba]
Code
Chr(160) === "\xA0"
[/vba]
KuklP, если воспользоваться предложенной моей регой + Trim
Quote (Alex_ST)
из текстовых значений ячеек удаляются все лидирующие, финиширующие пробелы. Каждый из многократно повторяющихся пробелов внутри текста ячейки заменяется на единичный пробел.
Мой стартовый пост был оформлен 30.08.2010, а тэга {vba} и реги для его обработки тогда ещё не существовало. Поэтому процедура в том посте заключена в простые одинарные тэги {code}
А по поводу Areas замечание, конечно, правильное, можно будет и подпилить. Но у меня как-то пока ни разу не возникала потребность выделить несколько областей, а потом их почистить от пробелов. А вообще - не помешает, наверное… Сделаем. Не проблема.
Quote (KuklP)
А че код так коряво оформляет(форум)?
Мой стартовый пост был оформлен 30.08.2010, а тэга {vba} и реги для его обработки тогда ещё не существовало. Поэтому процедура в том посте заключена в простые одинарные тэги {code}
А по поводу Areas замечание, конечно, правильное, можно будет и подпилить. Но у меня как-то пока ни разу не возникала потребность выделить несколько областей, а потом их почистить от пробелов. А вообще - не помешает, наверное… Сделаем. Не проблема.Alex_ST
Леша, вижу ты не понимаешь, о чем я говорю. Когда ты в range указываешь: .SpecialCells(xlCellTypeConstants), этот самый range может разделиться на несколько areas. Так вот вместо того, чтоб циклить по одной ячейке, за один проход будет обрабатываться целая область. Так гораздо быстрей.
Леша, вижу ты не понимаешь, о чем я говорю. Когда ты в range указываешь: .SpecialCells(xlCellTypeConstants), этот самый range может разделиться на несколько areas. Так вот вместо того, чтоб циклить по одной ячейке, за один проход будет обрабатываться целая область. Так гораздо быстрей.KuklP
Ну с НДС и мы чего-то стoим! kuklp60@gmail.com WM Z206653985942, R334086032478, U238399322728
Саша, ты что по Лешиному коду не видишь? А по моему? Он убирает лидирующие, замыкающие, множественные пробелы, то же до и после переносов строк, но сами переносы оставляет нетронутыми.
Quote (nerv)
Мне кто-нибудь объяснит?
Саша, ты что по Лешиному коду не видишь? А по моему? Он убирает лидирующие, замыкающие, множественные пробелы, то же до и после переносов строк, но сами переносы оставляет нетронутыми.KuklP
Ну с НДС и мы чего-то стoим! kuklp60@gmail.com WM Z206653985942, R334086032478, U238399322728