Страницы: Пред. 1 2
RSS
удалить из ячейки все символы, кроме кириллицы
 
Знаю, что есть люди на этом форуме, как я, любящие Excel и программирование (или по отдельности :) ).Делюсь своими наработками по этой теме, быстрее навряд ли получится у  меня (поблагодарю и поучусь, у кого получится улучшить время). Итак функция RusCh() - быстрее в 10 раз оптимизированного варианта от Андрея. Файл прилагаю (прилично времени ушло, что бы всё засунуть в 100КБ!!! в xlsm.)
Вариант для Excel-x64
«Бритва Оккама» или «Принцип Калашникова»?
 
Вариант для Excel-x32
«Бритва Оккама» или «Принцип Калашникова»?
 
Протестировать можно в модуле "Rus" процедура "Test_Rus()".
Никаких С# и Excel-DNA нет. Только С/С++, только Хардкор (кто понимает о чем я, Char*, BSTR, LPCSTR, указатели и нулевой байт!-самая мякотка! не эти, ваши, безопасные/медленные строки в C#)
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, спасибо вам большое!  :idea:
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Опрос по теме: жизнеспособен ли вариант со встраиваемой библиотекой(dll, xll) если ускоряется работа на порядок, но нужно написать библиотеку + добавить механизм запаковки\распаковки в файл excel? В итоге та же переносимость, как и у обычных функций (в т.ч. и своих надстройках) см.пример выше. Удобно ли это? Принимаю любые аргументированные мнения.  Что думаете отцы форума? Для стороннего пользователя разницы нет, или есть? (можно создать отдельную тему если вопрос выходит за рамки данной темы, но задал я его в следствии проработки именно этой темы)
Изменено: bedvit - 26.09.2017 23:11:12
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
bedvit написал:
Только С/С++
Круто! Не, я прикладник :( . Хотя, мне С# хватает. По работе, так вообще приходится Aris script теребить.
Цитата
bedvit написал:
по теме: жизнеспособен ли вариант со встраиваемой библиотекой(dll, xll)
Да, конечно, кому надо задействует, а остальные, как всегда - мне бы формулой для Excel по древнее.
По коду, не обязательно идти путём, предложенным Игорем, хранить его как текст на листе. Можно сразу бинарно хранить данные в CustomProperty листа (Open FileName As Binary и Get, Put через байт-массив). Я так для одного клиента SQLite врапер в xlsb хранил, чтобы он мог со своей базой где нужно работать.
 
В действительности строки в С# не столь медленные (контейнер для char* C-го языка) особенно если включить unsafe, и указатели. Просто Библа больше и не вылезает в 100 КБ. и несколько медленнее, все же прямое обращение к памяти в С++. Но как вариант С# то же неплох. Особенно с кучей библиотек и наработок со свободной лицензией.
Цитата
Андрей VG написал:
Можно сразу бинарно хранить данные в CustomProperty листа
Андрей, очень интересно! есть ресурс - почитать? Ещё   сейчас хочу регистрировать функции в xll, что бы не декларировать в модуле - ищу адекватное описание, не занимались этой темой?
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
bedvit написал:
очень интересно!
Кусок проекта. В Module1 как загружать в свойство. В коде листа ParameterSheet как выгружать. Файл не помещается, так что здесь.
Цитата
bedvit написал:
регистрировать функции в xll
Увы, этим не занимался. Я по колхозному, через Параметры/Надстройки добавляю.
Успехов.
 
Здравствуйте, коллеги!

"Правильную" скорость при подключении dll можно узнать, заменив в замечательно оптимизированном примере #24 вызов функции removeNonRussian в процедуре test на вызов следующей функции, выполняющий аналогичный (даже чуть больший) объем работ:



Код
#If VBA7 Then
   Private Declare PtrSafe Function CharToOem _
     Lib "user32" Alias "CharToOemA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
  
#Else
   Private Declare Function CharToOem _
     Lib "user32.dll" Alias "CharToOemA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
#End If

Function TestString(ByVal this As String)
 
 TestString = this
 CharToOem this, TestString
  
End Function


Время выполнения уменьшается примерно в 10 раз, так что можно поздравить bedvit c практически неулучшаемым результатом.
Изменено: sokol92 - 01.10.2017 15:27:27
Владимир
 
Андрей VG, не могу открыть ссылку, сможете обновить? (вышел из недельного отпуска, раньше не смог посмотреть, спасибо!)
sokol92, не полностью могу согласится с вашей методикой теста. Функция CharToOem переводит строку в набор символов, определенный OEM (CharToOemW (Unicode) и CharToOemA (ANSI)). И? Как это соответствует функционалу моей функции? Строка в С это и есть набор символов, не уверен что
Цитата
sokol92 написал:
выполняющий аналогичный (даже чуть больший) объем работ
У меня идет еще и перебор и проверка каждого символа, формирование нового стека Char*-в (символов). В итоге судя по вашим тестам (с одинаковым временем работы моей функции и функции "CharToOemA" в стандарнтной библиотеки "user32.dll") , бОльшая часть времени выполнение - это ввод-вывод, меньшая - сам расчет (могу ошибаться, тестить некогда). Но за тест спасибо!
«Бритва Оккама» или «Принцип Калашникова»?
 
Уважаемый bedvit! Функция CharToOemA (насколько мне известно) получает указатели на две области памяти (буфера): исходный и целевой. Функция анализирует каждый символ исходного буфера и преобразует его (по таблице перекодировки) в символ целевого буфера. Конечно, алгоритм преобразования отличается от Вашего, но для оценки времени выполнения это и не важно (учитывая скорострельность С). Сопоставимость времени выполнения функций означает, что Вы применили технологию, сопоставимую с той, которая используется в Windows для решения аналогичных задач, и вряд ли возможно принципиальное ускорение алгоритма.
Владимир
 
Хорошо, убедили - в данном контексте, пожалуй, соглашусь. Спасибо за инфо! Есть некая мысль, если выгорит - выложу решение (осталось найти время на реализацию). Андрей ваш файл скачал - спасибо! Пока не  разбирал - вопрос с ходу - залить можно несколько файлов?
Изменено: bedvit - 02.10.2017 22:03:01
«Бритва Оккама» или «Принцип Калашникова»?
 
Да, конечно. Каждому своё имя свойства. Только один момент, хоть CustomProperties выглядит как коллекция, но по имени значение не возвращает
 
Казалось бы тема закрыта, но все была одна идея, вообщем её я реализовал.
Возможно ешё что-то оптимизировать? Кажется этот вопрос уже закрыт. Но...
Вот что получилось...
Стоило ли это усилий?

Итак, написав 3 разных библиотеки и одну функцию в VBA, выкладываю результаты тестирования.
Моя машина ОЗУ-16Гб DDR3, ЦП Core i7-3770 (8 лог.ядер).
Библиотеки для Excel x64 (начиная с 2007).

Результаты:
Обработка 100 тыс. строк
Циклом в VBA (модуль RUS)
1.Функция VBA - 110 секунд, размер - в файле Excel.
2.xll созданная с помощью С# + Excel-DNA запуск через Application.Run - 19,3 сек., размер 543 КБ.
3.Библиотека dll написанная на С (Си) и задекларированная в VBA (Declare) - запуск просто в функции 11,69 сек. (лучший результат, т.к. работает напрямую минуя Application.Run), размер 84 КБ.
3. Собственно сам сабж - xll написанная на С (Си) через WINAPI (Thread-Safe) запуск через Application.Run -один поток - 18,16 сек., размер 15 КБ.

Усилия по созданию xll начинают казаться напрасными.

Переходим к работе напрямую с листом (через функции) копируем на 100 тыс. строк (Модуль TEST).
1.Функция VBA - 111,23 секунды, почти так же.
2.xll созданная с помощью С# + Excel-DNA 14,43 секунды - уже быстрее, все же это xll созданный именно для работы с листом.
3.Библиотека dll написанная на С (Си) и задекларированная в VBA (Declare) - 14,84 сек. (результат хуже, обертка Excel кушает)
3. Собственно сам сабж - xll написанная на С (Си) через WINAPI (Thread-Safe) - 8 потоков - 1,77!!! секунды (работа на 8 ядрах).

...структура данных XLOPER(XLOPER12) - замечательна вещь!
Файл-тест здесь.
Изменено: bedvit - 17.10.2017 21:46:17
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, круто! А с
Цитата
bedvit написал:
2.xll созданная с помощью С# + Excel-DNA 14,43 секунды
не пробловали ExcelFunctionAttribute.IsTrheadSafe = True?
 
Цитата
Андрей VG написал:
bedvit , круто!
Спасибо! не зря писал )
Цитата
Андрей VG написал:
ExcelFunctionAttribute.IsTrheadSafe = True?
Дамал, но в процессе реализации как-то потерялось..) Там как с памятью, Excel-DNA сам рулит? Видимо нужно писать и потокобезопасные переменные? В винрарной xll XLOPER12 - не любит работать, а любит пожрать-с... Если вручную не отжать у него память, всю сожрет :)
Изменено: bedvit - 18.10.2017 12:30:21
«Бритва Оккама» или «Принцип Калашникова»?
 
Проверил - нет, нужно потокобезопасные переменные делать
«Бритва Оккама» или «Принцип Калашникова»?
 
Поменял алгоритм для библы на Excel-DNA (для потокобезопасного вычисления).
Андрей, вариант "xll созданная с помощью С# + Excel-DNA" - многопоточный режим - [ExcelFunction(IsThreadSafe = true)]
Результат:
RELEASE 2-е тестирование
VBA
Excel_xll-AddIn64-packed.xll (C#+Excel-DNA) 17,75
Лист-функция
Excel_xll-AddIn64-packed.xll (C#+Excel-DNA) (Thread-Safe) -3,035156 - 8 потоков

Всё же проигрывает ванильной xll, я думал будут примерно равны результаты.
Тест
Изменено: bedvit - 18.10.2017 12:29:23 (убрал лишние пробелы между строками)
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
bedvit написал:
вариант "xll созданная с помощью С# + Excel-DNA" - многопоточный режим - [ExcelFunction(IsThreadSafe = true)]
Отлично, большое спасибо.
Цитата
bedvit написал:
Всё же проигрывает ванильной xll,
Всё же работа через wrapper .Net - имеет накладные расходы... С другой стороны. нет проще для кодирования и широтой готового, особенно для построения интерфейса, если не брать написание только функций.
Ещё раз спасибо за исследование.
Изменено: Андрей VG - 18.10.2017 12:30:42
 
Итого если обобщить:
-для работы именно в VBA, самый быстрый вариант пока выходит "Библиотека dll написанная на С (Си) и задекларированная в VBA (Declare)", возможно это не для всех задач, но пока нет других данных - считаем, что так.
-для работы с листом конкурентов нет у xll написанная на С (Си) через WINAPI (Thread-Safe), немного отстает xll созданная с помощью С# + Excel-DNA.
Но зато нет ручного управления памятью, никаких утечек памяти и "замечательных" XLOPER(XLOPER12). Но в скорости в 2 раза уступает лидеру.
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
Андрей VG написал:
С другой стороны. нет проще для кодирования
Согласен, после вашего сообщения зашел в проект на C# (скомпелировать новую библу) давненько не писал на С#, после почти чистого С и управления памятью, С# - как приятная прогулка (10-20 мин и новая структура и библа скомпилировани и главное работает и лишнего не жрет). Это как перейти с C# на VBA.
Утрирую немного, но после проекта на структуре XLOPER, ощущения такие :)
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
Андрей VG написал:
wrapper .Net - имеет накладные расходы...
плата за управляемый код (!?)
Цитата
Андрей VG написал:
Можно сразу бинарно хранить данные в CustomProperty листа (Open FileName As Binary и Get, Put через байт-массив).
Вещь! Немного под себя изменил, можно загружать, удалять, выгружать, смотреть загруженные файлы (в файле Excel). В прилагаемом файле все есть, набросал по-быстрому, если можно будет оптимизировать - с интересом приму предложения. Обгоняет решение от Игоря в 15 раз! (загрузка и выгрузка 100 МБ файла 10 сек. против 150 сек.) Андрей, ещё раз Спасибо!
Цитата
Андрей VG написал:
CustomProperties выглядит как коллекция, но по имени значение не возвращает
можно по-моему по порядковому номеру (!?).
ПО ТЕМЕ.Прилагаю конечный вариант (2 разновидности)
1.Excel .xlsb с самой быстрой функцией по этой теме (xll распаковывается автоматом) работает на Excel 2007 и выше как в х32 так и в х64 на всех ПК(должны быть включены макросы), но в файлах с этой функцией (внутри запакованной) - экспортный вариант
2.Библиотеки .xll подключить как надстройку (работает и без  включенных макросов), но на ПК на котором установлена (зато в любых Excel файлах, запаковывать и распаковывать библу в них не нужно) - экспортный вариант, стационарный вариант. Библиотеки можно распаковать из файла, для самых ленивых прилагаю ниже.

P.S. В функции реализовано описание, как для функции так и для переменной, есть СПРАВКА! Самые любопытные могут в ней отметится :)
Изменено: bedvit - 23.10.2017 09:41:22 (Библиотеки выложил в следующем сообщении для соблюдения размера вложений форума.)
«Бритва Оккама» или «Принцип Калашникова»?
 
vikttur, оставьте пожалуйста и отправьте в копилку. Хотя бы в порядке исключения — люди такой объём объём МЕГАПОЛЕЗНОЙ работы проделали  :cry:
если нужно — я сам закину на файлообменник и выложу ссылки, но только они же обнулятся со временем …
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Про исключения уже обсуждали.
 
Цитата
vikttur написал:
bedvit, размер вложения...
Цитата
Юрий М написал:
Про исключения уже обсуждали
Что нужно сделать? Разбить на 2 сообщения, библиотеки отдельно приложить? (на самом деле они есть в файле их просто нужно распаковать или забрать из "пользовательского темп" при авто-распаковке (выложил для ленивых). Готово, выложил библиотеки здесь.
Изменено: bedvit - 23.10.2017 09:43:52 (Добавил библиотеки из сообщения 52)
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, спасибо большое, всё ладно получилось!
 
Цитата
bedvit написал: мой алгоритм разбирает строку в байтовый массив, каждый символ - два байта в кодировке Unicode в десятичном представлении. И с массивом целых чисел работает, что очень быстро по сравнению с работой со строками. Формируется новый байтовый массив (заполняется старый) и выводится в строку итог (найденные нужные символы). Этим алгоритмом можно отсеивать или собирать любые символы Unicode довольно быстро.
за алгоритм - Спасибо!
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Решил попробовать сделать универсальную функцию, отстает всего в два раза от п.55, в счет универсальности.
Если будет интересна народу, можно будет и добавить функционал.
C API Excel - Получить строку с нужными символами Unicode.
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
JeyCi написал: алгоритм разбирает строку в байтовый массив, каждый символ - два байта в кодировке Unicode в десятичном представлении
полистала про Unicode (Глава 2) -
Рихтер Дж., Назар К. - Windows via C C++. Программирование на языке Visual C++ - 2009
- много интересного и Рекомендуемые приемы работы с символами и строками на стр.30
P.S.
для инфо- Стандарты кодирования символов ascii, ansi, кои-8 и unicode
Изменено: JeyCi - 28.09.2019 18:44:58
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Интересная задачка была..)
Изменено: testuser - 09.11.2023 16:00:24
Страницы: Пред. 1 2
Наверх