Range.Replace всегда верно для Chr(1)

Сейчас я в замешательстве. Я собирался создать ответ для этот вопрос.

Запустив некоторые тесты, я заметил, что

ActiveSheet.Cells.Replace Chr(1), "", xlPart, , True, , False, False

полностью очищает лист. Это имеет смысл для Chr(42), который равен *, но почему Chr(1)?

Кто-нибудь знает причину? Это какой-то второй/скрытый заполнитель?
(Что-то не удалось найти, но, вероятно, использовал неправильный поисковый запрос)


person Dirk Reichel    schedule 10.08.2017    source источник
comment
Интересный. Должна быть какая-то недокументированная функция.   -  person A.S.H    schedule 10.08.2017
comment
Всего 1 час... но похоже, что это закончится щедростью... и [A1].value = "-" & Chr(1) & "-" выглядит довольно странно :D   -  person Dirk Reichel    schedule 10.08.2017
comment
Это очень интересно. Вот что я нашел. Chr(1) означает Start of Heading, и вот документ (cs.tut.fi/~ jkorpela/chars/c0.html) описывает все управляющие символы ASCII. Другой правительственный веб-сайт (its.bldrdoc.gov/fs-1037/ dir-034/_5089.htm) имеет еще более запутанное объяснение Chr(1).   -  person ian0411    schedule 25.08.2017
comment
@ ian0411 Я знаю, что такое chr(1), я просто не понимаю, почему Excel ведет себя так, как со звездочкой (заполнителем), но не с любыми другими непечатаемыми символами. Кажется, что-то глубоко внутри самого приложения смущает Excel. Так что я любезен, если любопытно, что там происходит. (Тем не менее я уверен, что не могу понять это по-настоящему): P   -  person Dirk Reichel    schedule 25.08.2017
comment
Я так же сбит с толку, как и ты. Вы, вероятно, нашли особенность монстра, о которой MS даже не знает.   -  person ian0411    schedule 25.08.2017
comment
Еще интереснее то, что Chr(1) перемещает окончательный вариант через пробел, но его нельзя выбрать... и вы не можете найти и заменить Chr(1) без VBA.   -  person seadoggie01    schedule 13.09.2017
comment
Я предполагаю, что Chr(1) является реальным заполнителем (иначе было бы невозможно выполнить поиск *), но не имея возможности сделать именно это (насколько мне известно), это может быть некоторый остаток. Тем не менее, если ни один программист не остановится здесь случайно, я сомневаюсь, что получу правильный ответ. :/   -  person Dirk Reichel    schedule 13.09.2017
comment
К вашему сведению, хотя это и не совсем та же проблема, может быть интересно взглянуть на Почему Application.Clean удаляет печатные символы? stackoverflow.com/questions/27641324 /   -  person T.M.    schedule 20.09.2017
comment
Chr(63) что ? делает то же самое   -  person Karthick Gunasekaran    schedule 22.09.2017
comment
@KarthickGunasekaran ? - это заполнитель для одного символа, а * - это заполнитель для любого количества символов...   -  person Dirk Reichel    schedule 22.09.2017
comment
@Dirk Reichel, тогда почему он убирает все символы на листе   -  person Karthick Gunasekaran    schedule 22.09.2017
comment
@KarthickGunasekaran Поскольку вы ищете xlPart, все вхождения будут заменены (если заменить a на c, то aba станет cbc). Таким образом, все строки будут очищены char за char) ;)   -  person Dirk Reichel    schedule 23.09.2017
comment
Подробнее о chr(1) здесь и здесь.   -  person ashleedawg    schedule 18.10.2017
comment
@DirkReichel выглядит довольно странно, так что символы до 7, когда они только что введены в ячейку.   -  person Luuklag    schedule 24.10.2017
comment
Действительно интересный случай. Я обнаружил, что при добавлении нескольких экземпляров Chr(1) в одну ячейку и последующей замене их случайным значением он заменяется только один раз в этой ячейке. Поэтому я предполагаю, что на самом деле он не ищет это значение, а вместо этого заменяет любую непустую ячейку.   -  person Slaqr    schedule 22.11.2017
comment
При вставке нескольких экземпляров Chr(1) в строку и последующем выполнении для нее замены он перехватывает все экземпляры. Кажется, это странное поведение происходит только при прямой ссылке на ячейки.   -  person Slaqr    schedule 22.11.2017
comment
Он выдает мне ошибку времени выполнения '9': Subscript out of range :/   -  person AntiDrondert    schedule 28.11.2017
comment
Из любопытства - когда вы делаете это, если вы впоследствии сохраняете книгу, она каким-либо образом повреждается, когда вы пытаетесь открыть ее снова?   -  person SierraOscar    schedule 13.12.2017
comment
Я предполагаю, что поведение Excel связано с интерпретацией chr(1). Попробуйте запустить: SendKeys Chr(1) работает как CTRL+A, Chr(2) работает как CTRL+B и т. д. (подробнее здесь dc .org/files/asciitable.pdf). Возможно, vba интерпретирует chr(1) как «выбрать все», поэтому все непустые ячейки заменяются.   -  person TomJohnRiddle    schedule 22.01.2018
comment
@TomJohnRiddle, на самом деле, Chr (1) (среди прочего) не поддерживается Windows. Ваша догадка кажется правильной. Интерпретация Chr(1) в Excel будет состоять в том, чтобы выбрать все. В случае OP он заменится пустыми ячейками. Но посмотрите, что происходит, когда вы пытаетесь заменить на Hello. Это также будет работать на любом другом диапазоне :)   -  person JvdV    schedule 03.08.2018
comment
Я не уверен насчет выбора всей части. В некотором смысле это имеет смысл, но replace — это функция, которая сравнивает 2 строки. Если стоит 2.0 и вы попытаетесь заменить 0 на что-то, то ничего не произойдет, а на 2.01 сойдет. Таким образом, числовые значения будут преобразованы (игнорирует числовое форматирование). Простой поиск числа или строки не имеет значения. Он просто сравнивает 2 строки. Не будет выбрана ни одна ячейка или текст внутри ячеек. Если бы эта функция что-то выбирала, она была бы очень медленной. Также наличие chr(1) внутри ячейки не переворачивает эффект.   -  person Dirk Reichel    schedule 15.08.2018
comment
Хотя ActiveSheet.Cells.Find(Chr(1), ActiveCell).Activate также будет действовать так, как будто условие всегда выполняется, другие методы сравнения не показывают такого поведения, как instr(). И просто подсказка: это также работает, если вы откроете окно замены и вставите выражение Chr(1) в поле поиска. И еще одно противоречие для выбора всего: Microsoft Word вообще не показывает такого поведения.   -  person Dirk Reichel    schedule 15.08.2018


Ответы (4)


Причина может быть выяснена из разницы между

  • NUL : без символов. Он используется для заполнения времени или заполнения пространства на поверхности (например, на поверхности пластины) запоминающего устройства, где нет данных. Мы будем использовать этот символ, когда будем программировать очистители данных (как деструктивные, так и недеструктивные), чтобы стереть нераспределенное пространство, чтобы удаленные данные не могли быть восстановлены кем-либо или какой-либо программой.

  • SOH: этот символ используется для обозначения начала заголовка, который может содержать информацию об адресе или маршруте.

  • STX: этот символ используется для обозначения начала текста и, таким образом, также используется для обозначения конца заголовка.

Источник определения


В различных комментариях уже указывалось, что эти символы (первые 32) называются управляющими символами, потому что эти символы выполняют различные операции управления принтером и дисплеем, а не отображают символы.

В Hadoop SOH часто используется в качестве разделителя полей, особенно при чтении CSV-файлов. Кроме того, при открытии файла Excel (без распаковки в виде простого xlsx, т.е. в виде двоичного файла) в Notepad++ и печати управляющих символов можно увидеть много символов SOH. Из-за функций безопасности нельзя будет увидеть фактические данные.

chr(0) = SOH — указатель на адрес памяти всех ячеек, содержащих ТЕКСТ.

и

chr(1) = NUL — это указатель на адрес памяти всех ячеек, содержащих NULL или BLANK CELLS.

Давайте посмотрим на приведенные выше утверждения в отношении различных команд, показанных на изображении ниже. ВЕРХНИЙ СЛЕВА — это исходный диапазон данных, и пример показывает, как работает замена для SOH, NUL и ASTERISK (*) с использованием функции Range.Replace.

SOH Заменить ВСЕ в EXCEL


Итак, почему Chr(0) и Chr(1) могут заменить значения в ячейке Excel, если они являются просто указателями адресов, и почему chr(1) действует иначе, чем chr(42)?

Это происходит из-за структуры рабочего листа Excel. Когда вы открываете новую книгу Excel, ячейки Excel не помечаются. Это полностью визуально и в жесткой и в мягкой памяти системы.

Однако, как только кто-то вводит что-то в ячейку B2, всем ПУСТЫМ КЛЕТКАМ в квадрате до B2 будет присвоен указатель с Chr (0), а ячейке B2 будет назначен указатель с Chr (1).

Теперь, если удалить содержимое ячейки B2, то вместе с другими ячейками B2 будет назначен указатель NUL или Chr(0).

Это также является причиной того, что простая очистка содержимого с помощью Cells.ClearContents не очистит ячейки в памяти, а рабочая книга Excel раздувается, когда использовалась удаленная ячейка, но не удалялась с помощью Cells.Clear или Ctrl + Delete.


Теперь, когда понятно, почему Excel заменяет содержимое или очищает лист с помощью данной команды. Также важно понимать разницу между звездочкой (*) и SOH [или Chr(0)].

Звездочка (*) заменяет содержимое ячеек с минимальной длиной 0.

В то время как Chr (0) идентифицирует ячейки с SOH, то есть ячейки, содержащие значение, а затем заменяет значение в месте назначения указателя.

Разница не в результате, а в том, как находят или идентифицируют клетки, которые нужно заменить.


Я создал небольшой макрос для проверки гипотез, в котором записываю время, необходимое для замены полумиллиона ячеек (от A1 до CZ5000), используя Chr(1) = SOH и Chr(42) = *

Получается, что использование указателя на адрес ячеек с ТЕКСТом, т.е. SOH, занимает меньше времени, чем АСТЕРИСК (*).

Время замены текста


Sub Replace_Timer()

    Sheet3.Activate

    Dim startTime, endTime
    Dim i As Integer

        Sheet3.Range("A1:CZ5000").Value = "A"

    For i = 1 To 25
        startTime = Timer
            Sheet3.Cells.Replace Chr(1), "X", xlPart, xlRows, False
        endTime = Timer
        Sheet4.Cells(i + 1, 2).Value = endTime - startTime 'Execution time in miliseconds

        startTime = Timer
            Sheet3.Cells.Replace Chr(42), "Z", xlPart, xlRows, False
        endTime = Timer

        Sheet4.Cells(i + 1, 3).Value = endTime - startTime 'Execution time in miliseconds
    Next

    Sheet4.Activate

End Sub
person jainashish    schedule 21.02.2019
comment
Этот ответ объясняет все подробно, но при этом его легко понять. Чтобы выразить свою благодарность за этот отличный ответ, я добавил награду в 100 баллов, которая будет применена как можно скорее. (Баунти заблокированы на 24 часа) - person Dirk Reichel; 23.02.2019
comment
Я не уверен, что ваш тест действителен - когда я запускаю этот код, я получаю почти идеально равномерное распределение результатов для 25 итераций, причем примерно половина прогонов занимает больше времени с каждым методом. Функция Timer также возвращает секунды, а не миллисекунды ;-). - person Comintern; 23.02.2019
comment
Очень интересно. - person S Meaden; 25.02.2019

ASCII 1 — это «SOH» (начало заголовка), а ASCII 2 «STX» означает конец заголовка, начало потока данных. (Это позволяет вам «скрывать» адреса, заметки и т. д. в файле перед фактическими данными в файле.) Похоже, что Excel интерпретирует вашу команду, чтобы начать с начала файла и включить все.

person tysonwright    schedule 02.03.2018
comment
AFAIK excel проверяет строки внутри ячеек напрямую (а не данные в целом). Хотя это включает в себя форматирование, оно игнорирует структуру (поэтому вы не можете повредить файл). - person Dirk Reichel; 16.03.2018

Я думаю, что нашел ответ.
Как я нашел.
Я набрал "Alt+1" (1 с цифровой клавиатуры), а затем получил "?" (вопросительный знак).
Теперь я набрал ниже код, который очищает лист.

ActiveSheet.Cells.Replace "?", "", xlPart, , True, , False, False
person Community    schedule 15.03.2018
comment
Chr(1) возвращает SOH, что можно доказать. Так что это не причина извините :( - person Dirk Reichel; 16.03.2018
comment
Я пробовал в Excel, Alt + 1 дает мне улыбающееся лицо, но в непосредственном окне VBA он дает вопросительный знак! Однако Alt + 2, Alt + 3, Alt + 4 и т. д. --› все они показывают вопросительный знак в окне Immediate VBA и не очищают рабочий лист. Итак, вы хорошо постарались, но, к сожалению, это неправильное решение. - person jainashish; 03.07.2018

ASCII 1, как идентифицируют многие люди, интерпретируется приложениями как начало заголовка для каждого символа. Однако специальные символы можно экранировать некоторыми другими символами («~» — это экранирующий символ в Excel) отметьте здесь

Я считаю, что вам следует избегать замены на chr(1) в вашем коде.

person Sonu Kumar    schedule 22.03.2018