Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

21 Сентябрь 2018, 21:34 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Доступно и просто о работе в офисных пакетах
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1 2 »   Вниз
  Печать  
Автор Тема: Сравнение массиов в макросе  (Прочитано 2636 раз)
0 Пользователей и 1 Гость смотрят эту тему.
joshua
Форумчанин
***
Offline Offline

Сообщений: 51



« Стартовое сообщение: 31 Май 2017, 10:43 »

Господа подскажите пожалуйста, как эффективно сравнить два массива данных.
Есть два одномерных массива oAllData1 и oAllData2 , берутся из соответствующих диапазонов A1:A10 и  B1:B12 к примеру.
Нужно найти все элементы из массива oAllData2, которых нет в массиве oAllData1 и вывести их в отдельный массив

Ключевой аспект это скорость выполнения, так как элементов в обоих массивах может быть и 10 000 и 30 000

Sub GetAndSetData
Dim oRange1 'Основной диапазон
Dim oRange2 'Основной диапазон
Dim oSheet 'Первый лист
Dim oAllData1  'Массив, содержащий данные
Dim oAllData2  'Массив, содержащий данные

Dim s As String 'Основная строковая переменная
Dim i As Integer 'Основная индексная переменная
oSheet = ThisComponent.Sheets(0)
oRange1 = oSheet.getCellRangeByName("A1:A10")
oRange1 = oSheet.getCellRangeByName("B1:B12")
oAllData1 = oRange1.getDataArray()
oAllData2 = oRange2.getDataArray()
Непонимающий что дальше
End Sub
Записан
economist
Форумчанин
***
Offline Offline

Сообщений: 912


« Ответ #1: 31 Май 2017, 12:06 »

1) Если важна скорость, то формулами массива в ODS будет быстрее, чем на StarBasic.

2) Если нужны преобразования элементов "на лету" - макрос будет быстрее.

3) Если нужны преобразования (группировки, вычисления, подсчёты) в результирующем наборе - то правильнее именовать диапазоны, подключиться к ODS как к базе данных ODB и выполнить типовой SQL-запрос по возврату уникальностей из таблицы oAllData2.
Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
joshua
Форумчанин
***
Offline Offline

Сообщений: 51



« Ответ #2: 31 Май 2017, 12:09 »

1) Если важна скорость, то формулами массива в ODS будет быстрее, чем на StarBasic.
Что такое ODS?
Записан
mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 020


« Ответ #3: 31 Май 2017, 12:10 »

Код:
Sub SortRange(oCellRange)
  REM An array of sort fields determines the columns that are
  REM sorted. This is an array with two elements, 0 and 1.
  REM To sort on only one column, use:
  REM Dim oSortFields(0) As New com.sun.star.util.SortField
  Dim oSortFields(0) As New com.sun.star.util.SortField
 
  REM The sort descriptor is an array of properties.
  REM The primary property contains the sort fields.
  Dim oSortDesc(0) As New com.sun.star.beans.PropertyValue
 
  REM Select the range to sort.
  REM The only purpose would be to emphasize the sorted data.
  'ThisComponent.getCurrentController.select(oCellRange)
 
  REM Sort by range's first column ascending.
  oSortFields(0).Field = oCellRange.RangeAddress.StartColumn
  oSortFields(0).SortAscending = TRUE
 
  REM Setup the sort descriptor.
  oSortDesc(0).Name = "SortFields"
  oSortDesc(0).Value = oSortFields
 
  REM Sort the range.
  oCellRange.Sort oSortDesc
End Sub

Sub GetAndSetData
  time1 = now
  Dim oRange As Object'Основной диапазон
  Dim oSheet As Object 'Первый лист
  Dim oAllData1() 'Массив, содержащий данные
  Dim oAllData2() 'Массив, содержащий данные

  oSheet = ThisComponent.Sheets(0)
  oRange = oSheet.getCellRangeByName("A1:A30000")
  SortRange oRange
  oAllData1 = oRange.getDataArray()
  oRange = oSheet.getCellRangeByName("B1:B30000")
  SortRange oRange
  oAllData2 = oRange.getDataArray()
  
  Dim i As Integer, j As Integer, jMax As Integer 'Основная индексная переменная
  Dim oResultData(30000) 'Массив, содержащий данные
  Dim n As Integer : n = LBound(oResultData)

  j = LBound(oAllData2) : jMax = Ubound(oAllData2)
  For i = LBound(oAllData1) To Ubound(oAllData1)
    If (i > LBound(oAllData1)) Then
      If (oAllData1(i)(0) = oAllData1(i-1)(0)) Then
        GoTo Continue
      End If
    End If
    While ((oAllData2(j)(0) < oAllData1(i)(0)) And (j < jMax))
      j=j+1
    Wend

    If (oAllData2(j)(0) = oAllData1(i)(0)) Then
      oResultData(n) = oAllData1(i)(0)
      n = n + 1
      If (j < jMax) Then j=j+1
    End If
Continue:
  Next i
  ReDim Preserve oResultData(LBound(oResultData) To n)
  print Format(now - time1, "[ss]")
End Sub

У меня даёт 2-3 с на случайных числах
(я сортирую данные "на месте")
Записан

С уважением,
Михаил Каганский
economist
Форумчанин
***
Offline Offline

Сообщений: 912


« Ответ #4: 31 Май 2017, 12:36 »

joshua - ODS это единственный формат файла электронных таблиц OpenOffice|LibreOffice Calc, в котором макросы будут работать предсказуемо. В форматах файлов xls... это не так.
Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
joshua
Форумчанин
***
Offline Offline

Сообщений: 51



« Ответ #5: 31 Май 2017, 13:32 »

Спасибо, только у меня почему то ошибка вылезает Шокирован


* error basic.JPG (116.33 Кб, 1024x768 - просмотрено 12 раз.)
Записан
mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 020


« Ответ #6: 31 Май 2017, 14:28 »

Хм. AOO.

Код:
Sub SortRange(oCellRange)
  REM An array of sort fields determines the columns that are sorted
  Dim oSortFields(0) As New com.sun.star.util.SortField

  REM The sort descriptor is an array of properties.
  REM The primary property contains the sort fields.
  Dim oSortDesc(0) As New com.sun.star.beans.PropertyValue

  REM Sort by range's first column ascending.
  oSortFields(0).Field = 0
  oSortFields(0).SortAscending = TRUE

  REM Setup the sort descriptor.
  oSortDesc(0).Name = "SortFields"
  oSortDesc(0).Value = oSortFields

  REM Sort the range.
  oCellRange.Sort oSortDesc
End Sub

Sub GetAndSetData
  time1 = now
  Dim oRange As Object'Основной диапазон
  Dim oSheet As Object 'Первый лист
  Dim oAllData1() 'Массив, содержащий данные
  Dim oAllData2() 'Массив, содержащий данные

  oSheet = ThisComponent.Sheets(0)
  oRange = oSheet.getCellRangeByName("A1:A30000")
  SortRange oRange
  oAllData1 = oRange.getDataArray()
  oRange = oSheet.getCellRangeByName("B1:B30000")
  SortRange oRange
  oAllData2 = oRange.getDataArray()

  Dim s As String 'Основная строковая переменная
  Dim i As Integer, j As Integer, jMax As Integer 'Основная индексная переменная
  i = UBound(oAllData1) - LBound(oAllData1)
  j = UBound(oAllData2) - LBound(oAllData2)
  If (j<i) Then i = j
  Dim oResultData(0 to i) 'Массив, содержащий данные
  Dim n As Integer : n = LBound(oResultData)

  j = LBound(oAllData2) : jMax = Ubound(oAllData2)
  For i = LBound(oAllData1) To Ubound(oAllData1)
    If (i > LBound(oAllData1)) Then
      If (oAllData1(i)(0) = oAllData1(i-1)(0)) Then GoTo Continue
    End If
    While ((oAllData2(j)(0) < oAllData1(i)(0)) And (j < jMax))
      j=j+1
    Wend

    If (oAllData2(j)(0) = oAllData1(i)(0)) Then
      oResultData(n) = oAllData1(i)(0)
      n = n + 1
      If (j < jMax) Then j=j+1
    End If
Continue:
  Next i
  ReDim Preserve oResultData(0 To n-1)
  print Format(now - time1, "[ss]")
End Sub

Первая ошибка - моя. Я думал, что oSortFields(0).Field должна содержать номер столбца не в диапазоне, а на листе. Но это не имеет отношения к Вашему сообщению об ошибке. Просто второй столбец не сортировался, так что результат был бы корявым.

Вторая ошибка - AOO. Он не умеет получать LBound от массива внутри ReDim для этого массива. Отсюда и проблема.
Записан

С уважением,
Михаил Каганский
joshua
Форумчанин
***
Offline Offline

Сообщений: 51



« Ответ #7: 31 Май 2017, 15:07 »

Первая ошибка - моя. Я думал, что oSortFields(0).Field должна содержать номер столбца не в диапазоне, а на листе. Но это не имеет отношения к Вашему сообщению об ошибке. Просто второй столбец не сортировался, так что результат был бы корявым.

А что тогда надо написать вместо oSortFields(0).Field = oCellRange.RangeAddress.StartColumn ?
Записан
mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 020


« Ответ #8: 31 Май 2017, 15:09 »

Я же исправленный код вроде дал?
Записан

С уважением,
Михаил Каганский
joshua
Форумчанин
***
Offline Offline

Сообщений: 51



« Ответ #9: 31 Май 2017, 15:22 »

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

Но он состоит совсем из других значений



* CompareMassive.xls (8 Кб - загружено 5 раз.)
Записан
mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 020


« Ответ #10: 31 Май 2017, 15:30 »

Так. Не обращайте на меня внимания. Я тут совсем не то делал, что требовалось. Выбирал *совпадающие*.
« Последнее редактирование: 31 Май 2017, 15:41 от mikekaganski » Записан

С уважением,
Михаил Каганский
joshua
Форумчанин
***
Offline Offline

Сообщений: 51



« Ответ #11: 31 Май 2017, 15:42 »

Понял, столбцы переставил
Я попробовал с цифрами
в первом столбце
1 2 3 4 5 6 7 8 9 10 11 12 13
во втором
1 2 3 4 5 6 7 8 9 10
oResultData поидее должеть стать 11 12 13
а получается что oResultData(0) = 1 2 3 4 5 6 7 ...

* CompareMassive2.xls (8 Кб - загружено 3 раз.)
Записан
joshua
Форумчанин
***
Offline Offline

Сообщений: 51



« Ответ #12: 31 Май 2017, 15:44 »

Так. Не обращайте на меня внимания. Я тут совсем не то делал, что требовалось. Выбирал *совпадающие*.
))) Ну все равно спасибо тебе, теперь по-крайней мере есть эскиз, попробую что  нибудь из него получить)
Только я не понял что делает Sub SortRange(oCellRange)? сортирует каждый столбец по возрастанию?
Записан
mikekaganski
Мастер
*****
Online Online

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 020


« Ответ #13: 31 Май 2017, 15:51 »

Да, сортирует. Я же не знал, что они уже сортированные и уникальные. Можно было и проще при таких условиях.
Записан

С уважением,
Михаил Каганский
joshua
Форумчанин
***
Offline Offline

Сообщений: 51



« Ответ #14: 31 Май 2017, 15:54 »

Да, сортирует. Я же не знал, что они уже сортированные и уникальные. Можно было и проще при таких условиях.
Да не они на сам деле могут разные быть, это я для примера там взял. Так что сортировка пригодиться.
Записан
Страниц: 1 2 »   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!