Как использовать функцию pstr в Excel

Обновлено: 21.11.2024

Не вводите повторно ключи, которые можно извлечь с помощью строковой функции Excel. Научитесь использовать три большие строковые функции.

Windows: обязательно к прочтению

Вы злитесь, когда видите, что кто-то тратит драгоценное время? Да, и я не могу не сунуть свой нос и предложить лучший способ. Именно это произошло недавно, когда я заметил, что один из моих коллег использует Excel и вводит с нуля что-то, что можно было бы сгенерировать с помощью простой формулы. Вот совок.

Если текст встроен в ячейку, его можно извлечь.

Мой коллега получил от поставщика таблицу, содержащую столбец записей, похожий на те, что показаны на рисунке А.

Эти строки состояли из трех отдельных частей:

  • Первые три символа (числа K) представляют собой код продукта.
  • Вторые две цифры (цифры B) представляют код цены.
  • Последние три цифры представляют собой код клиента.

Моя коллега хотела разделить эти три части на разные столбцы и перепечатывала их с нуля! Такой подход настолько расточительный и неэффективный, что у меня мурашки по коже. К счастью, я стал героем, показав ей, как использовать строковые функции Excel для автоматического извлечения кодов.

Развлечение со строковыми функциями

Все вы, опытные пользователи электронных таблиц, знаете это упражнение наизусть. Вот как это работает.

Захват первых трех символов

Чтобы извлечь первые три символа текстовых записей, вы вводите функцию Left следующим образом:

В этом случае мы ввели в ячейку B2 функцию =Left(A2,3), а затем скопировали эту формулу в ячейки B3:B8. На рисунке Б показаны результаты.

Вытягивание двух символов посередине

Чтобы извлечь два символа из середины строки, мы воспользуемся функцией Mid, которая принимает следующий вид:

Поскольку мы знаем, что строка, которую мы хотим извлечь, всегда начинается с позиции 4, мы ввели в ячейку C2 функцию =Mid(A2,4,2), а затем скопировали эту формулу в ячейки C3:C8. На рисунке C показаны результаты.

Извлечение последних трех символов строки

Чтобы извлечь последние три символа строки, вы используете функцию Right в форме:

В нашем примере мы ввели в ячейку D2 функцию =Right(A2,3) и скопировали ее в ячейки D3:D8. Как показано на рис. D, эта функция возвращает три крайних правых символа в исходной строке.

Что делать после извлечения строк?

После того как вы использовали строковые функции для разбора исходной строки на подстроки, вы можете отсортировать данные или подвести промежуточные итоги по любому из столбцов, содержащих эти подстроки. На составление вызова функции и копирование его в соответствующие ячейки уходит всего одна-две минуты. Этот метод удобен, когда вы импортируете текстовые файлы, созданные из базы данных мэйнфрейма или из какого-либо другого приложения.

Конечно, мы только что коснулись того, что можно делать со строковыми функциями «большой тройки». В этом простом примере исходная строка всегда содержала одинаковое количество символов.

Знание того, что средняя строка всегда начинается с четвертой позиции, упрощает использование функции Mid. Но что, если подстрока, которую вы хотите извлечь, может начинаться в любом месте строки? В следующей статье мы покажем вам, как использовать функцию Find в сочетании с функцией Mid для поиска и извлечения строки независимо от того, сколько символов содержит исходная строка.

Чтобы прокомментировать эту статью или поделиться своим любимым советом по Excel, оставьте комментарий ниже или напишите нам.

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

Если функция должна выполнять запись в элемент, используйте _Inout_ вместо _In_ . Это особенно актуально в случаях автоматического преобразования старых макросов в SAL. До SAL многие программисты использовали макросы в качестве комментариев — макросы с именами IN , OUT , IN_OUT или вариантами этих имен. Хотя мы рекомендуем вам преобразовать эти макросы в SAL, мы также призываем вас быть осторожными при их преобразовании, поскольку код мог измениться с момента написания исходного прототипа, и старый макрос может больше не отражать то, что делает код. Будьте особенно осторожны с НЕОБЯЗАТЕЛЬНЫМ макрокомментарием, потому что он часто размещается неправильно, например, не с той стороны запятой.

_opt_

Если вызывающему объекту не разрешено передавать нулевой указатель, используйте _In_ или _Out_ вместо _In_opt_ или _Out_opt_ . Это применимо даже к функции, которая проверяет свои параметры и возвращает ошибку, если она равна NULL, хотя этого быть не должно. Хотя функция проверяет свой параметр на неожиданное значение NULL и корректно возвращает значение, это хорошая практика защитного кодирования, это не означает, что аннотация параметра может быть необязательного типа ( _*Xxx*_opt_ ).

_Pre_defensive_ и _Post_defensive_

Если функция появляется на границе доверия, мы рекомендуем использовать аннотацию _Pre_defensive_. Модификатор «defensive» изменяет некоторые аннотации, чтобы указать, что в точке вызова интерфейс должен строго проверяться, но в теле реализации он должен предполагать, что могут быть переданы неверные параметры. В этом случае _In_ _Pre_defensive_ предпочтительнее на границе доверия, чтобы указать, что, хотя вызывающий объект получит ошибку, если он попытается передать NULL, тело функции будет проанализировано, как если бы параметр мог быть NULL, и любые попытки разыменования указатель без предварительной проверки на NULL будет помечен. Также доступна аннотация _Post_defensive_ для использования в обратных вызовах, где предполагается, что доверенная сторона является вызывающей стороной, а ненадежный код является вызываемым кодом.

_Out_writes_

В следующем примере показано распространенное неправильное использование _Out_writes_ .

Аннотация _Out_writes_ означает, что у вас есть буфер. Он имеет выделенные байты cb, причем первый байт инициализируется при выходе. Эта аннотация не совсем неверна, и полезно указать выделенный размер. Однако он не сообщает, сколько элементов инициализируется функцией.

В следующем примере показаны три правильных способа полного указания точного размера инициализируемой части буфера.

_Out_ PSTR

Использование _Out_ PSTR почти всегда неверно. Эта комбинация интерпретируется как имеющая выходной параметр, указывающий на буфер символов, а буфер завершается нулем.

Такая аннотация, как _In_ PCSTR, является распространенной и полезной. Он указывает на входную строку с завершающим нулем, поскольку предварительное условие _In_ позволяет распознавать строку с завершающим нулем.

_In_ WCHAR* p

_In_ WCHAR* p говорит, что существует входной указатель p, указывающий на один символ. Однако в большинстве случаев это, вероятно, не та спецификация, которая предполагалась. Вместо этого, вероятно, имеется в виду спецификация массива, оканчивающегося нулем; для этого используйте _In_ PWSTR .

Обычно отсутствует правильная спецификация нулевого окончания. Используйте соответствующую версию STR для замены типа, как показано в следующем примере.

_Вне_диапазона_

Если параметр является указателем и вы хотите выразить диапазон значений элемента, на который указывает указатель, используйте _Deref_out_range_ вместо _Out_range_ . В следующем примере выражается диапазон *pcbFilled, а не pcbFilled.

_Deref_out_range_(0, cbSize) не является обязательным для некоторых инструментов, поскольку его можно вывести из _Out_writes_to_(cbSize,*pcbFilled) , но здесь он показан для полноты картины.

Неверный контекст в _When_

Еще одна распространенная ошибка – использование оценки после состояния для предварительных условий. В следующем примере _Requires_lock_held_ является предварительным условием.

Выражение return относится к значению пост-состояния, которое недоступно в предварительном состоянии.

ИСТИНА в _Успехе_

Если функция завершается успешно, когда возвращаемое значение не равно нулю, используйте return != 0 в качестве условия успеха вместо return == TRUE . Ненулевое значение не обязательно означает эквивалентность фактическому значению, которое компилятор предоставляет для TRUE. Параметр _Success_ является выражением, и следующие выражения оцениваются как эквивалентные: return != 0 , return != false , return != FALSE и return без параметров или сравнений.

Ссылочная переменная

Для ссылочной переменной предыдущая версия SAL использовала подразумеваемый указатель в качестве цели аннотации и требовала добавления __deref к аннотациям, прикрепленным к ссылочной переменной. Эта версия использует сам объект и не требует дополнительных _Deref_ .

Аннотации к возвращаемым значениям

В следующем примере показана распространенная проблема с аннотациями возвращаемых значений.

В этом примере _Out_opt_ говорит, что указатель может быть NULL как часть предварительного условия. Однако предварительные условия не могут применяться к возвращаемому значению. В этом случае правильная аннотация — _Ret_maybenull_ .

Функция RtlIpv4AddressToString преобразует IPv4-адрес в строку стандартного для Интернета десятичного формата с точками.

Синтаксис

Параметры

Адрес IPv4 в сетевом порядке байтов.

Указатель на буфер, в котором хранится строковое представление адреса IPv4, заканчивающееся нулем. Этот буфер должен быть достаточно большим, чтобы вместить не менее 16 символов.

Возвращаемое значение

Указатель на символ NULL, вставляемый в конце строкового представления адреса IPv4. Это может быть использовано вызывающей стороной для простого добавления дополнительной информации к строке.

Примечания

Функция RtlIpv4AddressToString используется для преобразования адреса IPv4 в строковое представление адреса IPv4 в десятичном формате с точками в Интернете.

RtlIpv4AddressToString — это удобная функция, которая не требует загрузки библиотеки DLL Windows Sockets для доступа к функции Windows Sockets для преобразования IP-адреса в строку.

Когда определены UNICODE или _UNICODE, RtlIpv4AddressToString определяется как RtlIpv4AddressToStringW, версия этой функции в Unicode. Строковый параметр S и возвращаемое значение функции определены для типа данных PWSTR.

Если и UNICODE, и _UNICODE не определены, RtlIpv4AddressToString определяется как RtlIpv4AddressToStringA, версия этой функции ANSI. Строковый параметр S и возвращаемое значение функции определены для типа данных PSTR.

Структура IN_ADDR определена в заголовочном файле Inaddr.h.

Библиотека импорта, содержащая функцию RtlIpv4AddressToString, не включена в пакет SDK для Microsoft Windows, выпущенный для Windows Vista. Функция RtlIpv4AddressToString включена в библиотеку импорта Ntdll.lib, включенную в комплект драйверов Windows (WDK). Приложение также может использовать функции GetModuleHandle и GetProcAddress для извлечения указателя функции из Ntdll.dll и вызова этой функции.

Заголовок ip2string.h определяет RtlIpv4AddressToString как псевдоним, который автоматически выбирает версию ANSI или Unicode этой функции на основе определения константы препроцессора UNICODE. Смешивание использования псевдонима, не зависящего от кодировки, с кодом, который не является нейтральным, может привести к несоответствиям, которые приводят к ошибкам компиляции или выполнения. Дополнительные сведения см. в разделе Соглашения для прототипов функций.

PROGMEM — это функция Arduino AVR, которая была портирована на ESP8266 для обеспечения совместимости с существующими библиотеками Arduino, а также для экономии оперативной памяти. На esp8266 объявление строки, такой как const char * xyz = «это строка», поместит эту строку в ОЗУ, а не во флэш-память. Можно поместить строку во флэш-память, а затем загрузить ее в ОЗУ, когда это необходимо. На 8-битном AVR этот процесс очень прост. На 32-битном ESP8266 есть условия, которые должны быть выполнены для обратного чтения из флэш-памяти.

На ESP8266 PROGMEM есть макрос:

ICACHE_RODATA_ATTR определяется:

Что помещает переменную в раздел .irom.text во flash. Для размещения строк во флэш-памяти необходимо использовать любой из описанных выше методов.

Объявите flash-строку внутри блока кода.¶

Для этого вы можете использовать макрос PSTR. Все они определены в pgmspace.h

В двух приведенных выше примерах эти строки будут храниться во flash. Для извлечения строк флэш-памяти и управления ими они должны считываться из флэш-памяти в 4-байтовых словах. В Arduino IDE для esp8266 есть несколько функций, которые могут помочь получить строки из флэш-памяти, которые были сохранены с помощью PROGMEM. Оба приведенных выше примера возвращают const char * . Однако использование этих указателей без правильного 32-битного выравнивания вызовет ошибку сегментации, и ESP8266 выйдет из строя. Вы должны прочитать из флэш-памяти 32-битное выравнивание.

Функции для чтения из PROGMEM¶

Все они определены в pgmspace.h

Там много функций, но на самом деле это версии _P стандартных функций c, которые адаптированы для чтения из 32-битной выровненной флэш-памяти esp8266. Все они принимают PGM_P, который по сути представляет собой const char *. Под капотом все эти функции используют процесс, обеспечивающий чтение 4 байтов и возврат байта запроса.

Это хорошо работает, когда вы разработали функцию, как описано выше, которая специализирована для работы с указателями PROGMEM, но нет проверки типов, кроме const char * . Это означает, что с точки зрения компилятора совершенно законно передавать ему любую строку const char *, что явно неверно и приведет к неопределенному поведению. Это делает невозможным создание каких-либо перегруженных функций, которые могут использовать флэш-строки, если они определены как PGM_P. Если вы попытаетесь, вы получите неоднозначную ошибку перегрузки, поскольку PGM_P == const char * .

Введите __FlashStringHelper… Это класс-оболочка, который позволяет использовать флэш-строки в качестве класса. Это означает, что с флэш-строками можно использовать проверку типов и перегрузку функций. Большинство людей знакомы с макросом F() и, возможно, с макросом FPSTR(). Они определены в WString.h:

Поэтому FPSTR() берет указатель PROGMEM на строку и приводит его к этому классу __FlashStringHelper. Таким образом, если вы определили строку как xyz выше, вы можете использовать FPSTR() для преобразования ее в __FlashStringHelper для передачи в функции, которые ее принимают.

Функция F() сочетает в себе оба этих метода, чтобы создать простой и быстрый способ сохранить встроенную строку во flash и вернуть тип __FlashStringHelper . Например:

Несмотря на то, что эти две функции выполняют схожие функции, они выполняют разные роли. FPSTR() позволяет определить глобальную строку флэш-памяти, а затем использовать ее в любой функции, которая принимает __FlashStringHelper.F() позволяет вам определить эти флеш-строки на месте, но вы не можете использовать их где-либо еще. Следствием этого является то, что совместное использование общих строк возможно с использованием FPSTR(), но не F(). __FlashStringHelper — это то, что класс String использует для перегрузки своего конструктора:

Это позволяет вам писать:

Как написать функцию для использования __FlashStringHelper? Простые: верните указатель на PGM_P и используйте функции _P, показанные выше. Это пример реализации String для функции concat.

Читайте также: