Вопрос по производительности макроса (перенос данных из csv в ods (>100к ячеек))

Автор Strohmann, 26 мая 2014, 08:05

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

Strohmann

Программно там точно всё хорошо в макросе? Я ведь вполне могу забивать гвозди микроскопом по неопытности.

Дальше должен формироваться отчёт, содержащий почасовые значения всех параметров (думаю, сформировать таблицу, свернуть все ряды за час (3600 рядов на каждый час =/) и выводить среднее значение параметра, с возможностью по клику развернуть подробную информацию) минимум, максимум (за час и всё время), также должна быть вкладка с графиками. В каком формате они нужны - пока не понятно, всё зависит от производительности. Но, думаю, что строить график за сутки по 86400 точкам - бессмысленно, логичнее - 3600 точек на час + 24 точки средних значений на сутки.

В общем, требуется в сжатом виде представить информацию по работе установки, с сохранением возможности получить максимально детальную информацию для анализа технологами. Плюс - получить возможность работать с этой информацией на любом ПК, а не только на инженерных станциях АСУТП, для чего и был затеян экспорт данных, ибо в WinCC и так довольно удобный анализ.

rami

С вашим макросом проблем нет. Я написал свой, но он может и быстрее, но не на много. Я не вижу смысла чтобы данные за один час обрабатывать несколько часов. Нужно как-то ускорить.
Для диаграммы время должно быть числом, а не строкой (хотя можно и строкой), а дубли на диаграмму не влияют.

Yakov

А если изначально загружать в массив?
А затем его уже обрабатывать (удалять лишние данные) и переводить данные в электронную таблицу?

Strohmann

Цитата: Yakov от 27 мая 2014, 09:17А если изначально загружать в массив?

Можете немного пояснить свою идею?

Yakov

Или, как было предложено ранее, загрузить данные во встроенную бд, там их обработать, а результирующую таблицу передать в Calc

Yakov

Цитата: Strohmann от 27 мая 2014, 09:35Можете немного пояснить свою идею?
Если создать стандартный массив,
и загрузить туда данные с помощью стандартной функции Line Input
Вот пример кода из справки по использованию этой функции

Sub ExampleWorkWithAFile
Dim iNumber As Integer
Dim sLine As String
Dim aFile As String
Dim sMsg as String
aFile = "c:\data.txt"
iNumber = Freefile
Open aFile For Output As #iNumber
Print #iNumber, "Это строка текста"
Print #iNumber, "Это еще одна строка текста"
Close #iNumber
iNumber = Freefile
Open aFile For Input As iNumber
While not eof(iNumber)
Line Input #iNumber, sLine
If sLine <>"" then
sMsg = sMsg & sLine & chr(13)
end if
wend
Close #iNumber
Msgbox sMsg
End Sub

JohnSUN

Цитата: Strohmann от 27 мая 2014, 10:35
Цитата: Yakov от 27 мая 2014, 09:17А если изначально загружать в массив?

Можете немного пояснить свою идею?
Это стандартное действие при работе с листами электронных книг: для указанного (или текущего) листа создается курсор, одной командой растягивается до последней ячейки с данными и опять-таки одной командой считывается в "массив массивов". Приблизительно так:
Sub example
Dim oSheet As Variant
Dim oCursor As Variant
Dim oDataArray As Variant
Dim oCells As Variant
Dim i&, j&
REM Получить нужный лист по номеру (в данном случае - первый)
oSheet = ThisComponent.getSheets().getByIndex(0)
REM Или получить текущий (активный) лист
REM oSheet = ThisComponent.getCurrentController().getActiveSheet()

REM Для выбранного листа создать курсор
oCursor = oSheet.createCursor()
REM "Растянуть" (на самом деле "обжать") курсор до последней используемой ячейки
oCursor.gotoEndOfUsedArea(True)
REM Считать все данные из ячеек, попавших в курсор
oDataArray = oCursor.getDataArray()
REM oDataArray - это "массив строк", каждый элемент в нём - это массив ячеек строки
REM Перебираем строки
For i = LBound(oDataArray) To UBound(oDataArray)
REM Забираем массив ячеек в отдельную переменную-массив и обрабатываем в отдельном цикле
oCells = oDataArray(i)
For j = LBound(oCells) To UBound(oCells)
REM Какие-то действия с элементами oCells(j)
Next j
Next i
End Sub
Чтение всего диапазона в массив занимает приблизительно столько же времени, как и чтение значения из одной ячейки. А значит скорость обработки данных возрастает многократно.
Более того, если результат обработки накапливать в таком же "массиве массивов", то и запись в лист делается одним оператором .setDataArray. Нужно только очень точно указать диапазон ячеек, в который будут записываться данные.

Но для данной задачи это действительно лишние телодвижения. Формат CSV изначально был создан для обмена данными между таблицами баз данных. Поэтому идея создать на его основе базу BASE и получить нужные значения одним SELECT DISTICT - самая правильная и быстрая.

Единственным препятствием для этого метода (и единственным оправданием для его неиспользования) может служить слабое знакомство с базами данных. Тогда действительно, Calc рулит.
Но и в этом случае макрос - не лучшее решение. (Типа, возвращаемся к теме, заявленной в названии) Питоньяк как-то провел исследование на тему "как быстрее", протестировал несколько вариантов макросов. Макрос, который всё делал сам оказался самым медленным, а последовательный вызов нескольких встроенных механизмов - самым быстрым.
Почему, например, не воспользоваться стандартным фильтром для диапазона с указанием "Без повторений" и копированием результата в нужное место?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Hasim

Самым лучшим было бы обрабатывать исходные csv до нужной кондиции в С, Pascal, Basic и т.п. - бесплатные варианты есть и очень простые.
А потом загружать их в LO и строить сразу графики.