Calc: Как лучше загрузить данные из файла?

Автор eeigor, 6 февраля 2023, 23:12

0 Пользователи и 1 гость просматривают эту тему.

eeigor

Подскажите, как лучше загрузить данные из файла? Мне надо загрузить данные из файла в формате электронной таблицы ODF (*.ods), добавить их к общей базе данных на другом листе, после чего загрузить следующий набор данных (в цикле). По окончании работы очистить лист загрузки. Речь идёт о диапазоне листа, но приходится загружать весь лист.

[Фрагмент] Данные в примере ниже загружаются на лист (зд. из файла Excel) методом листа <link>, после чего связь обрывается.
Dim sUrl$  'source document's URL
' Name of sheet in source document where contents are copied from.
' If this string is empty, source document's first sheet is used, regardless of its name.
Dim sSheetName$
' Filter name and options that are used to load source document.
Dim sFilterName$, sFilterOptions$
Dim nMode%  'enum value that controls how the contents are copied

' Convert a system-specific path to a URL (not necessary: sUrl == sFileName).
'sUrl = ConvertToUrl(sFileName)
sUrl = sFileName
sSheetName = "Лист1"
' Filter "Calc MS Excel 2007 VBA XML" works both for XLSM & XLSX.
sFilterName = "Calc MS Excel 2007 XML"
sFilterOptions = ""
' NOTE: If value is SheetLinkMode.NORMAL, formulas are copied.
' With SheetLinkMode.VALUE, only results of formulas are used.
nMode = com.sun.star.sheet.SheetLinkMode.VALUE
With ThisComponent
Rem .lockControllers
With .CurrentController.ActiveSheet
.link(sUrl, sSheetName, sFilterName, sFilterOptions, nMode)
.setLinkMode(com.sun.star.sheet.SheetLinkMode.NONE)
End With
Rem .unlockControllers
End With

Есть другие варианты?
UPD. Как-то иначе можно получить доступ к диапазону листа другого файла, чтобы не загружать весь лист?
Например: oDoc = OpenDocument(...): oSheet = oDoc.Sheets.getByName(sName): oRange = oSheet.getCellRangeByName(...)
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

Мы используем для аналогичных задач (например, чтения csv-файлов) метод insertAtPosition интерфейса XAreaLinks. Параметр этого метода aSourceArea позволяет задать диапазон импортируемых ячеек.
Владимир.

economist

Pandas прочтет листы ODF/XLSX/CSV-файлов в RAM целиком, соединит нужные строки и сохранит результат в ODF/XLSX/CSV в ~5-10 раз быстрее методов Calc. Для соединяемых десятков тысяч строк времени уйдет до секунды. При этом можно мимоходом обеспечить целостность индекса, непересекаемость данных, сортировку, заполнение пустот итд. Во столько же раз быстрее будет и кодинг.
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

sokol92

Цитата: economist от  7 февраля 2023, 14:40Pandas прочтет листы ODF/XLSX/CSV-файлов в RAM целиком, соединит нужные строки и сохранит результат в ODF/XLSX/CSV в ~5-10 раз быстрее методов Calc.
Методы Calc написаны на С/С++, так же, как и Pandas. Так что в каждом конкретном случае такие высказывания подлежат проверке. По моих ощущениям, c csv-файлами метод insertAtPosition работает эффективно.
Владимир.

economist

Готов поучаствовать в соцкапсоревновании на скорость сбора значений из нужных частей ODS/XLS/CSV-таблиц Pandas vs Calc, на стороне бамбукового медведя. Если задача с вычислениями и логическими проверками, например на моно-типы значений в колонках - еще лучше. Синтетика неинтересна - предлагаю дождаться похожего вопроса на Форуме - и бахнуть код.
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

eeigor

#5
Цитата: sokol92 от  7 февраля 2023, 13:36Мы используем для аналогичных задач (например, чтения csv-файлов) метод insertAtPosition.
Владимир, спасибо за наводку. Метод понравился. Я импортирую именованный диапазон ячеек и обрываю связь.
   With ThisComponent.AreaLinks
      .insertAtPosition oFirstCell.CellAddress, sFileName, "Табель", "", ""
      .removeByIndex 0
   End With
Правда, формулы замещаются значениями. Метод имеет два последних параметра (фильтр и параметры фильтра), нельзя ли их задействовать? Кто подскажет? Сейчас эти 2 строковых параметра я заменил пустой строкой (см. в примере выше).
Parameters
aFilter   the name of the filter used to load the source document. – Зд. можно задать "calc8" или оставить "".
aFilterOptions   optional filter options for the specified filter. – "" (?)

UPD. Было, что можно сохранить формулы, но речь шла об экспорте/импорте *.csv файла (Token 10, csv export: Export cell formulas. String, either false or true. Default value: false. Token 13, csv import. Determines whether formula expressions starting with a = equal sign character are to be evaluated as formulas or imported as textual data). Но нужен импорт из ods файла с формулами. В Интернете нет информации по этому вопросу.
Фильтры:
https://help.libreoffice.org/latest/en-US/text/shared/guide/convertfilters.html
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

eeigor

#6
Загрузил данные на скрытый лист (файлов >1, поэтому в цикле), вставил формулы вместо значений, скопировал в общую базу данных, то есть в именованный диапазон, предварительно расширив его для приема данных. Метод листа copyRange формулы переносит.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

eeigor

Мысли вслух (офтопик):
Плохо, что у диапазона нет свойства Formula, а есть только FormulaArray. Массив затрудняет в последующем манипуляции со строками, а присваивать, используя относительную нотацию, одинаковую формулу каждой ячейке диапазона в цикле неэффективно. Excel такое свойство, вроде имеет.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

Свойство диапазона ячеек Formula в Excel аналогично FormulaArray в Calc.
Свойству Formula прямоугольного диапазона, состоящего более, чем из одной ячейки, можно присваивать как строку, так и массив.
Вопрос на знание Excel. Что будет в ячейках A1:A3, если мы выделим A1:A3 и выполним макрос:
Selection.Formula = "=B1+C1"
В LO UNO в силу поддержки множества языков аргументы методов почти всегда строго типизированы. Для размножения формул вполне подходит метод fillAuto.
Владимир.

eeigor

#9
Вероятно, одно и то же:
=B1+C1
Метод fillAuto был отклонён из-за отказа работать со скрытым столбцом и заменён на .uno:FillDown. «Мысли вслух» появились в процессе поиска решения. Для присваивания значения ячейке использую пользовательскую процедуру SetFormulaR1C1 (FormulaParser).
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

mikekaganski

Цитата: eeigor от 20 марта 2023, 14:27SetFormulaR1C1 (FormulaParser)

Если Вы используете FormulaParser, то Вы можете задавать формулу и в нотации A1.
С уважением,
Михаил Каганский

sokol92

Владимир.