Тестирование производительности таблиц офисных пакетов в Linux на примере MS Office, LibreOffice, МойОфис, OnlyOffice

bc9accathtyvme7ijko5vs2210a.png
Актуальность темы обусловлена форсированием перехода Государственных ведомств и госкомпаний России с Windows на Astra Linux. Это было сделано на фоне заявления корпорации Microsoft о сворачивании бизнеса в РФ. Так как у автора, да и у многих других пользователей MS Office, за долгие годы работы скопилось ряд наработок, то вопрос об их работоспособности и переносе под новый офисный пакет, на платформе Linux, стоит остро, как и возможность малой автоматизации рутинных действий.

1. Введение


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

У каждого инженера со стажем рано или поздно скапливается множество программок, табличек, макросов упрощающих или облегчающих работу. Однако учитывая тот факт, что на законодательном уровне принято решение о прекращении закупок импортного ПО для критической информационной инфраструктуры и набирающие обороты процессы импортозамещения, на мой взгляд, пришло время поговорить о том, как рядовой инженер, скажем инженер-сметчик/инженер-ПТО сможет перевести часть своего легаси (устаревший код, который больше не поддерживается, не обновляется, но используется) на один из предлагающихся к импортозамещению офисных пакетов.

2. Сравнение и тестирование функциональности и производительности Офисных пакетов в Linux


2.1 Информация об оборудовании на котором будет происходить тестирование
Тестирование производительности я произвел на ноутбуке Hasee ZX7-CT5DA (он же Clevo N957TC), обзор которого я уже делал ранее на данном ресурсе, с предустановленным гипервизором Proxmox, в виртуальной машине с проброшенной видеокартой. При этом гостевой операционной системой для тестов у меня используется полюбившийся мне Debian 11.3 non-free

Характеристики ноутбука:
ЦП — Intel Core i7–8700
ВК — GTX 1660Ti
ОЗУ — 16 GB
Установленные диски — 512GB Phison SSD SATA m.2/1TB Kingston KC2500 SSD NVMe m.2/250GB Samsung EVO 850 SSD SATA 2.5»
Дисплей — 15,6 ''IPS 45% NTSC

Настройки виртуальной машины
7t7hae0ujqj2l1y9ith3gb9ojkk.png
ProxMox работает на 1TB Kingston KC2500 SSD NVMe m.2, на нем же хранятся файлы виртуальных машин. Несмотря на проброшенный диск 512GB Phison SSD SATA m.2 в тестировании он участвовать не будет и служит лишь для обмена данными между виртуальной машиной и хостом (устройство, предоставляющее сервисы, выступающее сервером).

Тест дисковой подсистемы на хосте
Тест дисковой подсистемы в виртуальной машине
cnntkxpt_drzzas5zxmhixknlfa.png


2.2 Краткая характеристика тестируемого ПО
MicroSoft Office 2010, установленный при помощи PlayOnLinux в Wine. Ныне устаревший офисный пакет от MicroSoft будет выступать в качестве системы для легаси, который необходимо будет перенести в другой офисный пакет по результатам тестов. 2010-я версия выбрана лишь только потому что, в моем случае, это последняя версия, которая устанавливается без проблем в PlayOnLinux на моей конфигурации в Debian 11. В общем и целом в представлении не нуждается.

Внешний вид MicroSoft Office
6afk6d4mjt-mgc2nmmibr-v5fxu.png


LibreOffice 7.0.4.2 — стандартный офисный пакет, который шел в комплекте с Debian 11.

Кроссплатформенный, свободно распространяемый офисный пакет с открытым исходным кодом, созданный как ответвление OpenOffice.org в 2010 году. Разрабатывается сообществом из более чем 480 программистов под эгидой некоммерческого фонда The Document Foundation за счёт пожертвований отдельных лиц и организаций.

по заверениям Wikipedia

Внешний вид и Версия LibreOffice
nzki28guomp7l6hwwqcpbqgxn9y.png
umjoca0ijmwyzngub_dumsgx_we.png


МойОфис Домашняя версия 2022.01. Сборка 4 — по моему скромному мнению офис, менеджеры которого наиболее активны в PR’е на различных площадках с целью продвижения своего продукта.

Экосистема приложений для совместной работы с документами с возможностью интеграции в закрытые облачные инфраструктуры и специализированные информационные системы. Разработчик «Новые облачные технологии» Продукты МойОфис включены в Единый реестр российских программ для электронных вычислительных машин и баз данных, полностью соответствуют законодательству РФ и дополнительным требованиям к офисному ПО, согласно постановлению Правительства №325 от 23 марта 2017 года. Приложения ориентированы на коммерческих и государственных заказчиков, сертифицированы на соответствие требованиям по информационной безопасности ФСТЭК, ФСБ и МО РФ и могут применяться для работы с конфиденциальной информацией и сведениями, составляющими государственную тайну.

по заверениям Wikipedia

Внешний вид и Версия МойОфис
bwfnemuhjgfdfqwylwy_yehf9lw.png
wtft2xosnxemhzd6dgrbdyrfss4.png


OnlyOffice Desktop Editors версия 7.1.0.215

Офисный пакет с открытым исходным кодом, разработанный компанией Ascensio System SIA с головным офисом в Риге (Латвия). Решение включает в себя систему для управления документами, проектами, взаимоотношениями с клиентами и электронной почтой.
Доступны облачная версия и версия для развертывания в локальной сети. Кроме того, редакторы ONLYOFFICE интегрируются с популярными платформами для совместной работы, включая ownCloud, Nextcloud, SharePoint и другими. ONLYOFFICE является официальным технологическим партнером Nextcloud, ownCloud, SeaFile, Pydio, eXo Platform и XWiki.

по заверениям Wikipedia

Внешний вид и Версия OnlyOffice
i2j2vqsqfd8i0m1vktztp3ur_xk.png2ry-2jujwa4wh6byha8wafniguy.png


Другие офисные программы в рамках данной статьи расматриваться не будут по разным причинам, например потому что WPS Office в бесплатной версии не имеет макросов, зато заявлена поддержка VBA, OpenOffice не встает в систему рядом с LibreOffice и требует его полного удаления, Р7-Офис — мои земляки, требует обязательную регистрацию что, на мой взгляд, совершенно неоправданно с т.з. популяризации ПО.

По сути из Российского ПО здесь только МойОфис, наверное на этом можно можно было бы и закончить не начав, но все же я продолжу, потому что и OnlyOffice открыл код редакторов под лицензией GNU AGPL v. 3, и LibreOffice под общественной лицензией MPL 2.0, а значит есть все основания сравнивать Российское ПО с открытым.

2.3 Постановка задачи
Производится Сравнение и тестирование Табличных редакторов Офисных пакетов будет с точки зрения удобства и функциональности программирования простых, но крайне необходимых макросов, которые будут автоматизировать работу в части формирования и заполнения шаблонных документов, а так же будет частично затронут вопрос работоспособности ключевых формул, которые будут помогать в форматировании и подготовке таких документов.

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

2.4 Интерфейс и формулы
Далее будут приводится скриншоты для каждой операции каждого офисного табличного процессора из указанных выше офисных пакетов: MS Excel, LibreOffice Calc, МойОфис Таблицы Домашняя версия, OnlyOffice Таблица.
Последующий текст будет ориентирован на продвинутого пользователя программного пакета MS Office для русскоязычных пользователей. В конце статьи будет ссылка на файлы, в которых будут хранится все этапы тестов, для тех кто захочет попробовать повторить и сравнить на своих ПК.

2.4.1 Именованные диапазоны
Именованный диапазон это ячейка/диапазон ячеек, которому присвоено имя. Применяется в формулах, для определения границ печати (в MS Excel для выводимого диапазона на печать всегда присваивается имя диапазону Область_печати), а так же для выпадающих списков, но это мы немного забегаем вперед.

Для того что бы создать Именованный диапазон необходимо:
а) в MS Excel открыть вкладку «Формулы» и выбрать пункт «Диспетчер имен»

Скриншот окна в MS Excel
6dr1hqnna69uossr8budtyzen-m.png

б) в LibreOffice Calc выделить диапазон данных, открыть меню «Данные» и выбрать пункт «Задать диапазон…»

Скриншот окна в LibreOffice Calc
r_plu1792wzgym82dxmzxt4z1gy.png

в) в МойОфис Таблицы Домашняя версияможно использовать именованные диапазоны, созданные только с помощью сторонних программ, по состоянию на июнь 2022 года.

Скриншот окна в МойОфис Таблицы Домашняя версия
-bacolzd8kjfe2ionkb1tui1vaa.pngn_rpnmyzbyfpqalhbmxooaec8ti.png

г) в OnlyOffice Таблица открыть вкладку «Формула», выбрать меню «Именованные диапазоны» и выбрать пункт «Диспетчер имен»

Скриншот окна в OnlyOffice Таблица
yibvqxzbfudmx6drzf6s7lrgvry.png


2.4.2 Выпадающий список в ячейке
Выпадающий список в ячейке служит, с одной стороны, для удобства Пользователя при выборе регламентированных вариантов ответа, с другой стороны, исключаются случайные ошибки при заполнении значениями там где это важно. При этом будьте аккуратными, потому что если ссылаться напрямую на диапазон ячеек отличный от текущего листа, то в MS Office 2007 и младше приводит к сбросу настроек выпадающего списка в ячейке через непродолжительное время. Но для MS Office 2013 и старше это уже не так актуально, поэтому для порядка и удобства ссылки на такие списки лучше делать через Именованный диапазон.

Для того что бы создать Выпадающий список в ячейке необходимо:
а) в MS Excel открыть вкладку «Данные» и выбрать пункт «Проверка данных»

Скриншот окна в MS Excel
oyqytn65p5dkpvi6kkdevgpblhi.png

б) в LibreOffice Calc открыть меню «Данные» и выбрать пункт «Проверка…»

Скриншот окна в LibreOffice Calc
c9kzw9h_vnq5z9fatltlcbvexrc.png

в) в МойОфис Таблицы Домашняя версия, по состоянию на июнь 2022 года, выпадающий список своими средствами или сделанный в другом офисном пакете, сделать/задействовать невозможно.

Скриншот окна в МойОфис Таблицы Домашняя версия
wsom8cppl994knkvzky7xbxlryu.png

г) в OnlyOffice Таблица открыть вкладку «Данные» и выбрать пункт «Проверка данных».

Скриншот окна в OnlyOffice Таблица
58t1c_wjufixq-4xfvfgb94azki.png


2.4.3 Условное форматирование
Условное форматирование (цветовая раскраска и форматирование текста) применяют тогда и там, когда привносят в таблицы элемент дизайна и наглядности, и когда необходимо выделить ошибки/выбивающиеся значение и т.д. и т.п., т.е. все то на что необходимо заострить/обратить внимание. Такое форматирование ячеек происходит по различным наборам условий.

Для того что бы создать Условное форматирование в ячейке необходимо:
а) в MS Excel выделить диапазон ячеек, открыть вкладку «Главная», открыть меню «Условное форматирование» и выбрать пункт «Создать правило…»

Скриншот окна в MS Excel
amwlhuqcirqcf-fjnd_zia6sdhs.png

б) в LibreOffice Calc выделить диапазон ячеек, открыть меню «Формат», открыть подменю «Условное» и выбрать пункт «Условие…»

Скриншот окна в LibreOffice Calc
tvj-k0yjrdady2m7hbryc2hx1cq.png

в) в МойОфис Таблицы Домашняя версия, по состоянию на июнь 2022 года, функционал Условного форматирования своими средствами сделать невозможно, но файлы созданные в других офисных программах отрабатываются корректно.

Скриншот окна в МойОфис Таблицы Домашняя версия
cwpcoioexpgtz5spsnpetqgrjp4.png

г) в OnlyOffice Таблица выделить диапазон ячеек, открыть вкладку «Главная», открыть меню «Условное форматирование» и выбрать пункт «Новое правило»

Скриншот окна в OnlyOffice Таблица
9hkugc9z10w6fxge_v2palvgeqa.png


2.4.4 Получить диапазон области печати текущего листа формулой
Этот пункт и следующий будут из разряда колдунства. Такие функции необходимы в том случае, если Вам необходимо решать вопросы форматирования таблица/шаблона с учетом вывода на печать/принтер. Для этого используется формула MS Excel, которая для текущего листа выводит адрес диапазона печати в формате диапазона ячеек. Как мы помним MS Excel хранит диапазоны печати в именованных диапазонах «Область_печати», а так же оперативно отслеживает ее изменение в случае изменения границ области печати. =СЦЕПИТЬ(АДРЕС(СТРОКА(Область_печати);СТОЛБЕЦ(Область_печати);1;1);":";АДРЕС(СТРОКА(Область_печати)+ЧСТРОК(Область_печати)-1;СТОЛБЕЦ(Область_печати)+ЧИСЛСТОЛБ(Область_печати)-1;1;1))

После ввода формулы в ячейке:
а) в MS Excel обязательно настроить область печати на текущем листе и радоваться рабочей формуле. При настраивании области печати автоматически создается именованный диапазон с именем «Область_печати»

Скриншот окна в MS Excel
9dkhwwvl2mfla6qs7lyo4ttjtbu.png

б) в LibreOffice Calc данный способ не работает, в этом табличном процессоре не поддерживается функция MS Excel ЧИСЛСТОЛБ, а LibreOffice Calc при задании границ печати не создает именованный диапазон со значениями для печати и хранит данные в другом виде. Если загрузить предварительно сохраненный рабочий файл в MS Excel, то формула отразит последнее значение отображенное в таблице при закрытии в MS Excel. Соответственно этот вариант не работает, т.е. нужен другой подход.

Скриншот окна в LibreOffice Calc
8hpw8xqvufcjr46jlthvaz7nm7e.pngufvqiqgaknklikye6gnpa_xpkh0.png

в) в МойОфис Таблицы Домашняя версия после ввода формулы в ячейке и задания границ печати получаем ошибку, т.к. у офисного пакета МойОфис сложные отношения с Именованными диапазонами. Если загрузить предварительно сохраненный рабочий файл в MS Excel, то мы получим нерабочую формулу.

Скриншот окна в МойОфис Таблицы Домашняя версия
op5j19iban7mpnq7fxmuh8l2hsq.pnghy5u9us7wizzjexpq3ykhe_zvts.png

г) в OnlyOffice Таблица обязательно настроить область печати на текущем листе и радоваться рабочей формуле.

Скриншот окна в OnlyOffice Таблица
iekkum8nroqfxx1ynko5x73hhtk.png


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

Формула + объяснение
Первая строка в A3:
=ПСТР(A1;1;105-ПОИСКПОЗ(" *";ПРАВСИМВ(ПСТР(A1;1;105);СТРОКА($B$1:$C$104));))
Вторая и последующие строки A4 и далее (протянуть):
=ПСТР(A$1;СУММ(ДЛСТР(A$3:A3))+2;105-2-ПОИСКПОЗ(" *";ПРАВСИМВ(ПСТР(A$1;СУММ(ДЛСТР(A$3:A3));105);СТРОКА($B$1:$C$104));))

Вводить формулы только через комбинацию клавиш Ctrl+Shift+Enter (в случае MS Excel)
Здесь:
— число 105 — максимальное число символов в строке, т.е. 105 символов;
— A1, ПСТР (A$1 — жесткая привязка на ячейку в которой содержится текст, который требуется разбить на несколько строк. При правках сохранять знак символа $;
— ДЛСТР (A$3: A3) — диапазон строк перед текущей строкой, необходим для определения начала позиции для копирования последующего блока текста. При правках сохранять знак символа $;
— СТРОКА ($B$1:$C$104) — малофункциональный блок, который лучше не трогать, но стоит иметь ввиду, что если Ваш блок будет после 104-й строки, то необходимо будет диапазон скорректировать в сторону увеличения до максимальной строки в Вашем блоке текста. При правках сохранять знак символа $


После ввода формул в ячейке:
а) в MS Excel в ячейку А1 забиваем очень длинную тестовую фразу, с количеством символов больше 105 в несколько раз и радуемся результату:

Скриншот окна в MS Excel
gpvqvgtpe9choynbw3enjw0xc0s.png

б) в LibreOffice Calc данный способ не работает, т.к. он не знает функцию ПРАВСИМВ, а так же мне сходу не удалось запустить эти формулы ни через одну из комбинаций клавиш. Если загрузить предварительно сохраненный рабочий файл в MS Excel, то формула так же не работает. Соответственно нужен другой подход.

Скриншот окна в LibreOffice Calc
vvjqhmml4qwsbonaw8d_h9hjpga.pngvvjqhmml4qwsbonaw8d_h9hjpga.png

в) в МойОфис Таблицы Домашняя версия после ввода формулы в ячейки ведет себя так же как и LibreOffice Calc, с той лишь разницей, что у МойОфис нет проблем с функцией ПРАВСИМВ.

Скриншот окна в МойОфис Таблицы Домашняя версия
xq2kp6oz9t37skrvs9di8upnnkm.pngsfqneduvyymmakfkafsaoacc-5w.png

г) в OnlyOffice Таблица после ввода формулы в ячейки ведет себя так же как и LibreOffice Calc и МойОфис Таблицы Домашняя версия. Если загрузить предварительно сохраненный рабочий файл в MS Excel, то первоначально отображает вид как перед закрытием, но в случае правок в ячейке А1 пересчет формул заканчивается ошибкой.

Скриншот окна в OnlyOffice Таблица
ctlqu7pvy4ns3gpkbneiqpjms9y.pngmmf1utqyrd5tmudctkhv9crxtp4.png


2.4.6 Открытие файлов с большим количеством строк
6jecplkmmosrufpc0e6u0hnwur0.png
jo9afhrukw_fa-keklo8s7wkztq.png
Достаточно простой тест на ресурсоемкость. Давайте представим что у нас есть файл с большим числом строк данных, выгруженных из условной 1С, для чего смоделируем утрированную нагрузку, для этого:

а) в MS Excel в ячейку A1 вводим арабскую единицу, в соседнюю ячейку B1 вводим формулу »=A1+1», протягиваем ячейку B1 вправо до тех пор, пока не будет цифра 100, а затем копируем формулы на 11750 строк, получаем файл размером 9,1Мб и радуемся результату:

Скриншот окна в MS Excel
rrt0iflz5kuek4tfh7xu4081gh0.png

При этом сам MS Excel в оперативной памяти занимает порядка 251 308 КиБ, прокрутка работает быстро и плавно, а так же ничего не тормозит.
б) в LibreOffice Calc открытие того же самого файла осуществляется быстро, прокрутка осуществляется быстро и плавно, а так же ничего не тормозит. В оперативной памяти LibreOffice Calc занимает порядка 701 254 КиБ.

Скриншот окна в LibreOffice Calc
h5rfanvmj4schfsz2iykiqfkclc.png

в) в МойОфис Таблицы Домашняя версия открытие того же файла началось с вывода окна ожидания, прокрутка осуществляется с заметными глазу небольшими задержками, скролинг осуществляется неудобно из-за постоянных подгрузок, в оперативной памяти МойОфис Таблицы Домашняя версия занимает порядка 1 858 726 КиБ.

Скриншот окна в МойОфис Таблицы Домашняя версия
vzrxrnmg9i9pcihsvmk9phqbxae.pngjb4r8ttzzlasfwod3ikzotemavk.png

г) в OnlyOffice Таблица открытие того же файла осуществляется быстро, прокрутка происходит быстро и плавно, хотя на мой взгляд не такая плавная как LibreOffice Calc, в оперативной памяти OnlyOffice Таблица занимает порядка 618 188 КиБ.

Скриншот окна в OnlyOffice Таблица
3vi8pv5etqikr9fyxgmxyls9nsc.png


2.5 Макросы
2.5.1 Краткий обзор редакторов Макросов в офисных пакетах
а) в MS Excel редактор VBA в представлении не нуждается. Visual Basic for Applications, на текущий момент, представляет собой немного упрощенную реализацию языка программирования Visual Basic 6.0. VBA, будучи языком, построенным на COM, позволяет использовать все доступные в операционной системе COM объекты и компоненты ActiveX.
VBA хорошо документирован. Справочная информация предоставлена как в локальном варианте, так и онлайн. Кроме того пользователи MS Office создали огромное число площадок, сайтов, групп, видео, книг по обучению и обмену опытом, в результате чего возможность программировать на VBA достаточно просто, т.к. относительно легко найти в сети подходящий пример, при условии что Вы правильно формулируете запрос.
Дополнительной возможностью, не мало важной для нас, является еще и тот факт, что выполнение макроса можно связать с кнопкой, которую можно расположить на рабочем листе книги, что так же повышает удобство.

Скриншот окна в MS Excel
2gmmgi8u0r3xcyghmw8vmf_9wbg.png

б) в LibreOffice Calc используется LibreOffice Basic (LO Basic, LibreOffice Basic, OOo Basic, он же StarBasic), который в свою очередь частично совместим с VBA, но реализован иначе, из-за чего мы имеем разную производительность абсолютно идентичных макросов. Справочная информация предоставлена как в локальном варианте, так и онлайн, однако ресурсов посвященных этому BASIC’у намного меньше чем у VBA, тем не менее совместимость с VBA частично помогает решать вопросы.
Дополнительной возможностью, немаловажной для нас, является еще и тот факт, что выполнение макроса можно связать с кнопкой, которую можно расположить на рабочем листе книги, что так же повышает удобство.

Скриншот окна в LibreOffice Calc
lqrnvx9zhm6lwvcqy0chvt1rbpa.png

в) в МойОфис Таблицы Домашняя версия в настоящий момент реализована поддержка Lua версии 5.3.2, который является свободно распространяемым, с открытым исходным кодом. На сколько я знаю, из широко известных программных продуктов, он так же используется для написания плагинов к FAR. Здесь по ссылке можно скачать справочник макрокоманд. В настоящий момент в рунете сообществ посвященных программированию на Lua только у FAR’а. Редактор имеет спартанский интерфейс, но есть поддержка, правда в тестовом режиме, записи макросов. Назначить кнопку для запуска макроса нельзя.

Скриншот окна в МойОфис Таблицы Домашняя версия
5tlmkpleg-venhbvha3jb6mt3ao.png

г) в OnlyOffice Таблица используется JavaScript API. Документация по нему… доступна на сайте разработчика. Интерфейс редактора макросов — спартанский, записи макросов нет. Назначить кнопку для запуска макроса нельзя.

Скриншот окна в OnlyOffice Таблица
7e34hubudafmqqvrdqronx_slym.png


2.5.2 Пишем тестирующий производительность макрос

Техзадание на макрос:

Тестовый этап №1 — в первую очередь нас интересует производительность операций ввода-вывода в ячейки. Для чего на каждом языке программирования будет написан код, который будет заполнять матрицу 1000×1000 ячеек случайными числами;
Тестовый этап №2 — затем будет осуществляться чтение с заполненного листа в массив (память);
Тестовый этап №3 — после чего макросом осуществим запись заполненного листа в 10 файлов на жесткий диск;
Все три тестовых этапа должны будут сопровождаться фиксацией времени выполнения каждого этапа, собственно это время мы и будем сравнивать в рамках статьи. Таким образом, мы протестируем операции ввода-вывода.

Ну, а теперь более развернуто по каждому из офисных пакетов.

2.6.2.1 Макрос VBA в MS Excel
lqgikvovfvunkiuftvtwvfzchzm.png

Макрос VBA в MS Excel
Rem -= Заполняем область на Лист1 1000х1000 ячеек случайными значениями до 1000 =-

        Dim wb As Workbook
        Dim x As Integer, y As Integer
        
            Set wb = ThisWorkbook
            wb.Sheets("Лист1").Cells(1, "B") = Format(time, "hh:mm:ss")
            Randomize time
            For x = 1 To 1000 Step 1
                For y = 1 To 1000 Step 1
                    wb.Sheets("Лист1").Cells(y + 6, x) = rnd * 1000
                Next y
            Next x
            wb.Sheets("Лист1").Cells(2, "B") = Format(time, "hh:mm:ss")

Rem -= Читаем область на Лист1 1000х1000 ячеек в массив в память устройства =-

        Dim q(1000, 1000) As Single
            For x = 1 To 1000 Step 1
                For y = 1 To 1000 Step 1
                    Let q(x, y) = wb.Sheets("Лист1").Cells(y + 6, x)
                Next y
            Next x
            wb.Sheets("Лист1").Cells(4, "B") = Format(time, "hh:mm:ss")
        
Rem -= Сохраняем Лист1 на жесткий диск в виде MS Excel фала 10 раз =-
        Dim ИмяФайла As String
            Application.DisplayAlerts = False
            For x = 1 To 10 Step 1
                Let ИмяФайла = ThisWorkbook.Path + "\" + "Test"
                Let ИмяФайла = ИмяФайла + CStr(x) + ".xlsx"
       
                wb.Sheets("Лист1").Copy
                ActiveWorkbook.SaveAs Filename:=ИмяФайла, _
                    FileFormat:=51
                    ActiveWindow.Close
            Next x
            Application.DisplayAlerts = True
            wb.Sheets("Лист1").Cells(6, "B") = Format(time, "hh:mm:ss")


Собственно, здесь все просто и без выкрутасов. Два вложенных цикла, в которых перебираются ячейки по X и Y, сперва заполняя случайными числами, а потом считывая их в массив. Сохранение тоже без каких-либо неожиданностей. Результат выполнения макроса в приведенном скриншоте.

2.6.2.2 Макрос LibreOffice Basic в LibreOffice Calc
p4lt3c8uitkrpfinq4olvyhzg1c.png

Макрос LibreOffice Basic в LibreOffice Calc
Rem -= Заполняем область на Лист1 1000х1000 ячеек случайными значениями до 1000 =-

        Dim wb As Workbook
        Dim x As Integer, y As Integer
        
            Set wb = ThisWorkbook
            wb.Sheets("Лист1").Cells(1, "B") = Format(time, "hh:mm:ss")
            Randomize time
            For x = 1 To 1000 Step 1
                For y = 1 To 1000 Step 1
                    wb.Sheets("Лист1").Cells(y + 6, x) = rnd * 1000
                Next y
            Next x
            wb.Sheets("Лист1").Cells(2, "B") = Format(time, "hh:mm:ss")

Rem -= Читаем область на Лист1 1000х1000 ячеек в массив в память устройства =-

        Dim q(1000, 1000) As Single
            For x = 1 To 1000 Step 1
                For y = 1 To 1000 Step 1
                    Let q(x, y) = wb.Sheets("Лист1").Cells(y + 6, x)
                Next y
            Next x
            wb.Sheets("Лист1").Cells(4, "B") = Format(time, "hh:mm:ss")
        
Rem -= Сохраняем Лист1 на жесткий диск в виде MS Excel фала 10 раз =-
        Dim ИмяФайла As String
            Application.DisplayAlerts = False
            For x = 1 To 10 Step 1
                Let ИмяФайла = ThisWorkbook.Path + "\" + "Test"
                Let ИмяФайла = ИмяФайла + CStr(x) + ".xlsx"
       
                wb.Sheets("Лист1").Copy
                ActiveWorkbook.SaveAs Filename:=ИмяФайла, _
                    FileFormat:=51
                    ActiveWindow.Close
            Next x
            Application.DisplayAlerts = True
            wb.Sheets("Лист1").Cells(6, "B") = Format(time, "hh:mm:ss")


Несмотря на то что VBA и LibreOffice Basic имеют отличия, в этом фрагменте макрос LibreOffice Basic идеально повторяет код для VBA. Так же все просто и без выкрутасов. Два вложенных цикла, в которых перебираются ячейки по X и Y, сперва заполняя случайными числами, а потом считывая их в массив. Сохранение тоже без каких-либо неожиданностей. Результат выполнения макроса в приведенном скриншоте. Заметна разница в операциях заполнения/чтения ячеек в файле, по сравнению с VBA, при чем на порядок, но тут же в 2,5 раза выше скорость доступа к диску, при записи файлов.

2.6.2.3 Макрос Lua в МойОфис Таблица Домашняя версия
3gwgylem4lgsobvhb2yt76waafy.png

Предвосхищая удивленный возглас — да, здесь все сложно. К сожалению мне не удалось разобраться с записью макросом таблиц в несколько файлов, а так же с передачей времени в переменную. Тут меня ждало фиаско: Lua позволяет работать со временем, т.е. можно получить текущее время в переменную и записать его в ячейку, но проблема в том, что os.time () здесь не работает, а при использовании DocumentAPI.DateTime из инструкции макрос выдает ошибку: либо nil, либо пусто, если прописать его в переменную с конвертацией типа в текст. Примеров по использованию этого API в сети нет. Соответственно все замеры времени сделаны на секундомере смартфона и содержат некоторую погрешность, в отличие от других случаев оценки времени для других Офисов в статье. Каюсь, ибо грешен.

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

Макрос Lua в МойОфис Таблица Домашняя версия
-- This macros is generated by the MacroRecorder feature.

function changeTableSelection(anchorOffsetRow, anchorOffsetColumn, cursorOffsetRow, cursorOffsetColumn)
    local selection = EditorAPI.getSelection()
    local tbl = selection:getTable()
    local beginRow = selection:getBeginRow() + anchorOffsetRow
    local beginColumn = selection:getBeginColumn() + anchorOffsetColumn
    local lastRow = cursorOffsetRow and selection:getLastRow() + cursorOffsetRow or beginRow
    local lastColumn = cursorOffsetColumn and selection:getLastColumn() + cursorOffsetColumn or beginColumn
    assert(beginRow >= 0 and beginRow <= lastRow, 'Selection goes out of the top border of the sheet')
    assert(beginColumn >= 0 and beginColumn <= lastColumn, 'Selection goes out of the left border of the sheet')
    if (lastRow >= tbl:getRowsCount()) then
        tbl:insertRowAfter(tbl:getRowsCount() - 1, false, lastRow - tbl:getRowsCount() + 1)
    end
    if (lastColumn >= tbl:getColumnsCount()) then
         tbl:insertColumnAfter(tbl:getColumnsCount() - 1, false, lastColumn - tbl:getColumnsCount() + 1)
    end
    local position = DocumentAPI.CellRangePosition(beginRow, beginColumn, lastRow, lastColumn)
    EditorAPI.setSelection(tbl:getCellRange(position))
end

function updateFormulaInCurrentCell(value)
    local selection = EditorAPI.getSelection()
    local cellPos = DocumentAPI.CellPosition(selection:getBeginRow(), selection:getBeginColumn())
    selection:getTable():getCell(cellPos):setContent(value)
end

--main
changeTableSelection(5, 2, nil, nil)
updateFormulaInCurrentCell('1')
EditorAPI.changeSelection(EditorAPI.SelectionMode.Move, EditorAPI.SelectionDirection.Down, EditorAPI.TableSelectionUnit.ToClosestCell)


Здесь монструозная текстом функция changeTableSelection вызывает смещение относительно текущей позиции курсора на задаваемое число ячеек по строкам и столбцам, а EditorAPI.changeSelection(EditorAPI.SelectionMode.Move, EditorAPI.SelectionDirection.Down, EditorAPI.TableSelectionUnit.ToClosestCell) сдвиг курсора после ввода на одну ячейку вниз. Собственно на этой механике постоянного перемещения курсора и строится адресация записи в ячейку, сама же запись происходит через функцию updateFormulaInCurrentCell. Пользуясь этим мы пишем Первый вариант макроса на заполнение поля 1000 на 1000 ячеек.

Первый вариант макроса на заполнение поля 1000 на 1000 ячеек.
-- This macros is generated by the MacroRecorder feature.

function changeTableSelection(anchorOffsetRow, anchorOffsetColumn, cursorOffsetRow, cursorOffsetColumn)
    local selection = EditorAPI.getSelection()
    local tbl = selection:getTable()
    local beginRow = selection:getBeginRow() + anchorOffsetRow
    local beginColumn = selection:getBeginColumn() + anchorOffsetColumn
    local lastRow = cursorOffsetRow and selection:getLastRow() + cursorOffsetRow or beginRow
    local lastColumn = cursorOffsetColumn and selection:getLastColumn() + cursorOffsetColumn or beginColumn
    assert(beginRow >= 0 and beginRow <= lastRow, 'Selection goes out of the top border of the sheet')
    assert(beginColumn >= 0 and beginColumn <= lastColumn, 'Selection goes out of the left border of the sheet')
    if (lastRow >= tbl:getRowsCount()) then
        tbl:insertRowAfter(tbl:getRowsCount() - 1, false, lastRow - tbl:getRowsCount() + 1)
    end
    if (lastColumn >= tbl:getColumnsCount()) then
         tbl:insertColumnAfter(tbl:getColumnsCount() - 1, false, lastColumn - tbl:getColumnsCount() + 1)
    end
    local position = DocumentAPI.CellRangePosition(beginRow, beginColumn, lastRow, lastColumn)
    EditorAPI.setSelection(tbl:getCellRange(position))
end

function updateFormulaInCurrentCell(value)
    local selection = EditorAPI.getSelection()
    local cellPos = DocumentAPI.CellPosition(selection:getBeginRow(), selection:getBeginColumn())
    selection:getTable():getCell(cellPos):setContent(value)
end

--main
-- перед стартом поместить курсор в ячейку А1

for x=1, 1000, 1 do
	for y=1, 1000, 1 do
		updateFormulaInCurrentCell(math.random()*1000)
                EditorAPI.changeSelection(EditorAPI.SelectionMode.Move, EditorAPI.SelectionDirection.Down, EditorAPI.TableSelectionUnit.ToClosestCell)
	end
	changeTableSelection(-1000, 1, nil, nil)
end


Тут нужно сказать еще об одном нюансе. МойОфис таблицы не позволяет иметь на листе кол-во столбцов больше 1000 (ALL). Что наводит на некоторые мысли связанные с ограничениями работы ПО.
Однако я отвлекся, т.к. время выполнения макроса было слишком большое, то мне пришлось оценивать скорость по выполнению лишь одной его части — записи одного столбца. При заполнении 1-го столбца на 1000 ячеек случайными числами от 1 до 1000 тратится время 1 мин. 54 сек. Таким образом поле 1000×1000 ячеек будет заполнено за время =(60+54)сек/столбец * 1000 столбцов / 60сек / 60 мин = 31,67час.

Однако в инструкции есть другой метод адресации для записи в ячейку через getCell(DocumentAPI.CellPosition(y, х)). Пишем теперь уже совсем простенький макрос:

Второй вариант макроса на заполнение поля 1000 на 1000 ячеек.
local tbl = document:getBlocks():getTable(1)

for x=0, 1000, 1 do
	for y=0, 1000, 1 do
        tbl:getCell(DocumentAPI.CellPosition(y, x)):setNumber(math.random()*1000)
	end
end


Что выглядит значительно проще для восприятия и логики работы, но при этом… Оценка времени велась так же: при заполнении 1-го столбца на 1000 ячеек случайными числами от 1 до 1000 тратится время 6 минут. Таким образом поле 1000×1000 ячеек будет заполнено за время = 6 мин/столбец * 1000 столбцов / 60 мин = 100час. Видимо из-за этой разницы функционал записи макроса генерирует не этот код, а другой, более объемный.

Дальше пишем макрос на чтение поля 1000×1000 ячеек в массив.

Чтение поля 1000×1000 ячеек в массив
local tbl = document:getBlocks():getTable(1)

Arr = {}
for x=1, 1000, 1 do
	Arr[x] = {}
	for y=1, 1000, 1 do
            Arr[x][y]=tostring(tbl:getCell(DocumentAPI.CellPosition(y-1, x-1)):getFormattedValue());
	end
end


Который выполняется за… 12 секунд. С чем связана такая разница между временем записи данными в ячейки и считыванием их в память на Lua в МойОфис — хороший вопрос!

При беглом знакомстве был выявлен минус работы с макросами это то, что область таблицы недоступна для навигации и правок, пока открыт редактор макросов. В том же MS Excel можно без проблем переключаться между таблицей и редактором. Так же, в отличие от того же редактора VBA, не исправляется регистр букв в соответствии с внутренними представлениями о прекрасном. Зато тут есть консоль в которую выводятся как ошибки выполнения, так и через print() содержание переменных, что удобно при отладке. Работа с массивами непривычна, т.к. они не жесткие, как я привык по Basic, Pascal, C. В сети мало информации и примеров. Документация на сайте представлена всего лишь одной инструкцией, которая хоть и идет с примерами, но их явно недостаточно. В сети нет сообществ по обмену опытом программирования макросами Lua в МойОфис, но, справедливости ради, есть сообщество по Lua, что не одно и то же. Нет жесткой типизации переменных. В общем это другая парадигма отличная от той что меня учили в 90-е… может это и хорошо, но в целом непривычно.

2.6.2.4 Макрос JS в OnlyOffice Desktop Editors
b--v7
    
            <p class=© Habrahabr.ru