Сортировка документов коллекции

Тема в разделе "Библиотеки скриптов", создана пользователем LuMee, 19 июл 2007.

  1. LuMee

    LuMee Well-Known Member

    Регистрация:
    2 май 2006
    Сообщения:
    477
    Симпатии:
    0
    Данное решение не претендует на сильно большую практическую ценность, однако может быть кому-то пригодится. Представляет оно собой простеньку библиотечку для сортировки массивов, которую я лично использую при создании отчетов.
    Библиотека включает в себя такие компоненты:
    1. функция CollectionToArray, которая тупо перегоняет NotesDocumentCollection в массив документов:
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">код</div></div><div class="sp-body"><div class="sp-content"><!--shcode--><pre><code class='ls'>Function CollectionToArray(collection As NotesDocumentCollection) As Variant
    Dim documents() As NotesDocument
    Dim doc As NotesDocument
    Dim counter As Integer

    Redim documents(collection.Count - 1)

    counter = 0
    Set doc = collection.GetFirstDocument()
    While Not doc Is Nothing
    Set documents(counter) = doc
    counter = counter + 1
    Set doc = collection.GetNextDocument(doc)
    Wend

    CollectionToArray = documents
    End Function[/CODE]
    2. Базовый класс Comparer. Объекты этого класса используются для сравнения между собой элементов сорируемого массива (по аналогии с Comparator'ом в Java):
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">код</div></div><div class="sp-body"><div class="sp-content"><!--shcode--><pre><code class='ls'>Class Comparer
    'Возвращает результат сравнения элементов:
    'отрицательное значение - если leftElement меньше rightElement
    'положительное значение - если leftElement больше rightElement
    'ноль - если элементы равны
    Public Function Compare(leftElement As Variant, rightElement As Variant) As Integer
    Compare = 0
    End Function
    End Class[/CODE]
    3. Наконец, собственно класс, выполняющий сортировку (использует метод быстрой сортировки):
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">код</div></div><div class="sp-body"><div class="sp-content"><!--shcode--><pre><code class='ls'>Class ArraySorter
    'Данный объект будет использоваться для сравнения элементов массива при сортировке
    Private comparer As Comparer

    'Конструктор. В качестве параметра принимает объект-компаратор, с помощью которого
    'будут сравниваться элементы массива. Параметр не должен иметь значение Nothing
    Public Sub New(comparer As Comparer)
    Set Me.comparer = comparer
    End Sub

    'Данный метод сортирует переданный в качестве параметра массив
    Public Sub Sort(array As Variant)
    If Not Isarray(array) Then Exit Sub

    Dim low As Integer, high As Integer
    low = Lbound(array)
    high = Ubound(array)
    'Сортируем методом быстрой сортировки
    QuickSort array, low, high, IsArrayOfObjects(array)
    End Sub

    'Алгоритм быстрой сортировки был позаимствован с Wikipedia, так что его не
    'комментирую. Единственное замечание - параметр isObjectArray - показывающий, какого
    'типа - примитивного или объектного - элементы находятся в массиве. Это необходимо
    'потому, что в LS для присвоения значений переменных примитивного и объектного типов
    'используются разные синтаксические конструкции, так что для успешного присвоения
    'необходимо знать, с каким типов в данный момент осуществляется работа
    Private Sub QuickSort(array As Variant, low As Integer, high As Integer,_
    isObjectArray As Variant)
    Dim i As Integer, j As Integer
    Dim pivot As Variant, tmp As Variant

    If isObjectArray Then
    Set pivot = array((low + high) \ 2)
    Else
    pivot = array((low + high) \ 2)
    End If
    i = low
    j = high

    Do Until i > j
    While comparer.Compare(pivot, array(i)) > 0
    i = i + 1
    Wend
    While comparer.Compare(pivot, array(j)) < 0
    j = j - 1
    Wend
    If i <= j Then
    If isObjectArray Then
    Set tmp = array(i)
    Set array(i) = array(j)
    Set array(j) = tmp
    Else
    tmp = array(i)
    array(i) = array(j)
    array(j) = tmp
    End If
    i = i + 1
    j = j - 1
    End If
    Loop
    If low < j Then QuickSort array, low, j, isObjectArray
    If high > i Then QuickSort array, i, high, isObjectArray
    End Sub

    'Возвращает True, если array представляет собой динамический или фиксированный массив
    'пользовательских или встроенных объектов
    Private Function IsArrayOfObjects(array As Variant) As Variant
    Dim t As Integer
    t = Datatype(array)

    'Расшифровка типа array:
    '8192 - код фиксированного массива
    '8704 - динамического массива
    '34 - код пользовательского объекта
    '35 - код встроенного объекта
    't будет равнятся сумме одного из элементов первой пары и одного из элементов
    'второй пары
    If _
    (t = 8192 + 34) Or _ 'Фиксированный массив пользовательских объектов
    (t = 8192 + 35) Or _ 'Динамический массив пользовательских объектов
    (t = 8704 + 34) Or _ 'Фиксированный массив встроенных объектов
    (t = 8704 + 35) _ 'Динамический массив встроенных объектов
    Then
    IsArrayOfObjects = True
    Else
    IsArrayOfObjects = False
    End If
    End Function
    End Class[/CODE]
    Идея использования всего этого безобразия проста: имеем массив, который надо отсортировать. Создаем для этого массива подкласс Comparer'а, который содержит нужную реализацию метода Compare (знающую, как правильно сравнивать элементы данного конкретного массива). Далее объект-компарер передается сортировщику, и тот уже сортирует массив.
    В качестве примера накатал класс DocumentFieldsComparer, который сравнивает два документа (NotesDocument) по значениям полей. Список полей, по которым надо сравнивать, передается в виде массива. В теории он способен адекватно переварить даже многозначные поля:
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">код</div></div><div class="sp-body"><div class="sp-content"><!--shcode--><pre><code class='ls'>Class DocumentFieldsComparer As Comparer
    'Массив, содержащий названия полей, по которым надо произвести сравнение
    Private fields() As String

    'Конструктор
    'Параметр fieldsList - массив с названиями полей. Может статическим или динамическим
    Public Sub New(fieldsList() As String)
    Dim i As Integer
    Redim Me.fields(Lbound(fieldsList) To Ubound(fieldsList)) As String

    For i = Lbound(fields) To Ubound(fields)
    fields(i) = fieldsList(i)
    Next
    End Sub

    'Возвращает -1, если левый документ "меньше" правого, 1 - если "больше", 0 - в случае
    '"равенства"
    Public Function Compare(leftElement As Variant, rightElement As Variant) As Integer
    Dim leftDoc As NotesDocument, rightDoc As NotesDocument
    Dim leftValue As Variant, rightValue As Variant
    Dim result As Integer, i As Integer

    Set leftDoc = leftElement
    Set rightDoc = rightElement

    result = 0
    i = Lbound(fields)
    'Поля документов сравниваются одно за другим, пока не будет получен результат,
    'отличный от равенства (одно поле "больше" другого) - тогда этот результат и будет
    'результатом сравнения документов, либо не закончится список полей, в этом случае
    'документы считаются "равными"
    While (result = 0) And (i <= Ubound(fields))
    result = CompareItemValues(leftDoc.GetItemValue(fields(i)),_
    rightDoc.GetItemValue(fields(i)))
    i = i + 1
    Wend

    Compare = result
    End Function

    'Вспомогательная функция, предназначенная для сравнения массивов значений полей
    'документов. Элементы сравниваются один за другим, пока не будет получен результат,
    'отличный от равенства, либо не будет достигнуто максимальное количество элементов в
    'одном из полей. В этом случае "большим" будет считаться то поле, в котором больше
    'элементов. Если количество элементов одинаково, поля считаются "равными"
    Private Function CompareItemValues(leftItem As Variant, rightItem As Variant) As Integer
    Dim endIndex As Integer
    Dim result As Integer, i As Integer

    'По умолчанию поля считаются "равными"
    result = 0

    'Определяем минимальное количество элементов в полях
    If Ubound(leftItem) <= Ubound(rightItem) Then
    endIndex = Ubound(leftItem)
    Else
    endIndex = Ubound(rightItem)
    End If

    'Сравниваем элементы один за другим, пока не будет выявлено "большее" поле или
    'не будут перебраны все элементы в одном из полей
    i = 0
    While (i <= endIndex) And (result = 0)
    If leftItem(i) < rightItem(i) Then
    result = -1
    Elseif leftItem(i) > rightItem(i) Then
    result = 1
    End If
    i = i + 1
    Wend

    'Если все элементы одного из полей уже обработаны, а превосходство одного поля
    'над другим не установлено, сравниваем поля по количеству элементов
    If result = 0 Then
    If Ubound(leftItem) < Ubound(rightItem) Then
    result = -1
    Elseif Ubound(leftItem) > Ubound(rightItem) Then
    result = 1
    End If
    End If

    CompareItemValues = result
    End Function
    End Class[/CODE]
    Использовать это можно следующим образом:
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">код</div></div><div class="sp-body"><div class="sp-content"><!--shcode--><pre><code class='ls'>Dim fields(0 To 1) As String 'поля, по которым будем сравнивать
    Dim collection As NotesDocumentCollection
    Dim documents As Variant
    Dim comparer As DocumentFieldsComparer
    Dim sorter As ArraySorter

    fields(0) = "FieldA"
    fields(1) = "FieldB"

    Set comparer = New DocumentFieldsComparer(fields)
    Set sorter = New ArraySorter(comparer)

    Set collection = ... 'получили где-то коллекцию документов, скажем, выполнив поиск по БД
    documents = CollectionToArray(collection)
    sorter.Sort documents

    Dim doc As NotesDocument
    Forall varDoc in documents
    Set doc = varDoc
    ... 'ну и дальше что-то с документами делаем
    End Forall[/CODE]
    В общем, вот, выставляю на суд общественности :)
     
  2. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    Всем привет!

    кто-нить решал или знает эффективный способ решения задачи сортировки документов из коллекции по заданному критерию?
    конкретезирую задачу:
    - пользователю предлагается на выбор документов вид (ws.PickListCollection), он выбирает нужные документы;
    - вид отображает двухуровневую иерархию документов, т.е. есть какие-то родительские и к ним есть один уровень дочерних (это не принципиально, но все же);
    - пользователь может указать как родительские так и дочерние документы, если пользователь указывает родительский, то его дочерние подтягиваются в коллекцию;

    сама суть вопроса: эффективно отсортировать документы в коллекции так, чтобы они шли в том порядке, в котором отсортированы в виде...
    результатом получить структуру содержащую набор документов (либо унидов) в определенном порядке.

    ***
    я предполагаю использовать для этого NotesViewNavigator, но пока не сообразил как :blink:


    ***
    еще, кто-нить проверял как хранятся данные в листе? в порядке добавления или как попало? :wacko:
     
  3. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    Ну идея такая.
    Можно получить notesView.AllEntries. Коллекция будет отсортированнная.
    Дальше циклом по твоим документам. Получаем энтри с помощью GetEntry. У энтри делаем GetPosition. А дальше понятно.


    Вопрос в том, можно ли указывать в GetEntry документ не из коллекции.
     
  4. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    в навигаторе точно получалось... мне вот через позицию не понравилась мысля (первое о чем подумал сам), т.к. оно возвращает текстовую фикню, через разделитель...

    в данный момент решил попробовать такой способ:
    подтянуть документы, вытянуть в строку те данные, что в колонках отображаются, каждого дока в один элемент массива, потом сортануть массив собакой... должно получится... правда, на большом кол-ве получим ошибку в 32 К... но пока не предполагается...
     
  5. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    А что в этом такого? Зато быстро, наверное, будет. Через нафигатор медленно. :blink:
    В принципе вручную данные отсортировать.

    Почему-то мне этот способ меньше нравится. :wacko:

    Потому-что нужно каждое поле делать строго ограниченной длины. Чтобы правильно сортировалось.

    Или приводить к одной длине.
     
  6. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    через нафигатор довольно быстро, причем говорят, что он быстрее, чем коллекция, правда, для каждого случая свое может быть...

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

    но, конечно, было бы интересно сделать нормальный, универсальный способ...

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

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.073
    Симпатии:
    299
    сортировка не имеющая (относительно) ограничения в 32К...
    джава, вот кусок кода с сортировкой и выводом:
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">код на Java</div></div><div class="sp-body"><div class="sp-content"><!--shcode--><pre><code class='java'> ProductVolumes(){
    volumes=new ArrayList();
    }
    //................................................................................
    .............................
    HashMap prodHash=(HashMap)distr_clientVolume.get(i);
    //prepare for sorting then sort
    Set keys=prodHash.keySet();
    List lst=Arrays.asList(keys.toArray());
    Collections.sort(lst);
    Iterator it=lst.iterator();
    //list formating and output
    while (it.hasNext()) {
    String stKey=(String)it.next();
    ProductVolumes prodVol=(ProductVolumes)prodHash.get(stKey);
    ArrayList volumes=prodVol.volumes;
    String s=stKey+";"+prodVol.prodName;
    for (int j=0; j<volumes.size();j++) {
    s=s+";"+nf.format((Double)volumes.get(j));
    }
    outWriter.write(stName+";" + s);
    outWriter.newLine();
    }[/CODE]
     
  8. duchan

    duchan Well-Known Member

    Регистрация:
    20 сен 2006
    Сообщения:
    105
    Симпатии:
    2
  9. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    че-то мне кажется, что кусочек не полный :)
    во всяком случае, я не разобрался полностью, да и яву я не очень хорошо знаю...
    но, задача не массив отсортировать, а документы из коллекции (либо массива) выстроить в то положение, в котором они в виде отображаются...
    сори, если я не правильно понял :)
     
  10. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    Плохой метод. В конструкторе идет перегон коллекции в массив документов, если я правильно понял.
    Код (Text):
    For i%=0 To DC
    Set Docs(i%).doc = Coll.GetNthDocument(i%+1)
    Это жрет очень много памяти. Я от такого отказался.
    Лучший метод, по-моему, создать массив NoteID и дергать документ из базы каждый раз. Достаточно быстро и не жрет памяти.
     
  11. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    очень интересный пример, спасибо

    возможно не оптимизированный, но не значит плохой :)
    где-то я встречал подобную рекомендацию - хранить массив NoteID, но кто-нить может сказать, на сколько это увеличивает число операций считывания с диска, и на сколько это лучше хранения всех доков в памяти?
    причем, эта рекомендация касается только очень больших массивов документов... 100 документов, к примеру, уже очень большой массив? :)
     
  12. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    Ну так проверь. С графиками. Пару часов займет. :)
    Только сейчас запустил. Почти 9000 документов. Память начала утекать как вода сквозь пальцы. Физическая доступная практически кончилась. Своп вырос в два раза. С около 600 метров до 1 Гб. :)
    Если делать через массив NoteID, то память практически не расходуется. За время построения около 30 метров ушло.
     
  13. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    давай по порядку :)
    плохой способ перечисления доков через Coll.GetNthDocument() - согласен, лучше getFirst/getNext

    объекты доков в памяти - физическая доступная, это сколько? :) на сколько ощущается разница в использовании диска между все доки в памяти и обращения к каждому отдельному? т.е. в одном случае гоняем своп, в другом - тащим доки...

    кроме того, для меня пока прозрачно, когда мы дергаем коллекцию, то мы получаем в памяти объект хранящий где-то в недрах набор, к примеру, NoteID или же, все-таки, объектов NotesDocument?..

    в любом случае, для того, чтобы получить массив NoteID, нам придется перебрать коллекцию, потом провести сравнение документов, а значит выполнить операции по считыванию с диска множество раз, т.е. преимущество использовании диска или памяти пока еще не явно...
    коннечно, памяти лучше использовать минимум :) но просто для интереса...
     
  14. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    Свободно было 70 Мб. По мере построения она уменьшалась, своп рос. Обращение к жд не мерил, т.к. жд на сервере. :)
    Локально сейчас некогда тестировать.

    Похоже, коллекция - это не массив документов, а массив ссылок. Ссылок на хелп нету, но это легко проверяется.

    В случае с жд не забываем про кэширование. Так что не всё так просто.
     
  15. duchan

    duchan Well-Known Member

    Регистрация:
    20 сен 2006
    Сообщения:
    105
    Симпатии:
    2
    Medevic, дык, ёлы-палы.... ну переделай код с получения из массива док-тов, на хранения NoteID. в данном случае это был пример, который КАЖДЫЙ может переделать под свои потребности...

    Кстати, я такого катострофического роста исползуемой памяти не наблюдал... может коллекция у тебя огроменная, или сами док-ты пухлые....

    P.S. вот и делай людям добро...
     
  16. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    Ты дал пример, а я прокомментировал его как мне видится со своей колокольни. Что в этом плохого?

    Да, есть с вложениями. Не очень пухлые, но их много.
     
  17. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    кеширование - все та же память, так что, есть ли разница? ;) шучу


    DuChan, пример на самом деле хороший, поэтому не ругайтесь :) но Medevic прав на счет оптимизации, поэтому не надо сразу уходить в тень и переставать делать людям добро :)

    можно попробовать доработать данный алгоритм таким образом, чтобы при формировании массива NoteID параллельно формировался массив параметров, которые позволили бы провести сравнение документов... тогда, в принципе, можно предположить, что мы получим некую "середину" в использовании памяти и диска... хз :)
     
  18. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    У меня так и сделано, оказывается. Вот мозги работали когда-то. :)
    Если интересно, могу выложить свой класс.
     
  19. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    выкладывай, че уж там :)
     
  20. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Класс</div></div><div class="sp-body"><div class="sp-content"><!--shcode--><pre><code class='ls'>Private Class SortArray
    Public element() As Variant
    Public order As Integer
    Sub New(lowerBound As Long, upperBound As Long, iorder As Integer)
    Redim element(lowerBound To upperBound)
    order = iorder
    End Sub
    End Class

    Public Class NoteIDArray
    Public db As NotesDatabase
    Public dc As NotesDocumentCollection
    Public fieldNames As String
    Public NoteIDArray() As String*8
    Private fieldSortArray List As SortArray

    Sub New(idb As NotesDatabase, idc As NotesDocumentCollection, ifieldNames As String)
    Dim dummy As Variant
    Set db = idb
    Set dc = idc
    fieldNames = Fulltrim(ifieldNames)
    Call DCToArr
    End Sub

    Private Sub DCToArr
    Dim doc As NotesDocument
    Dim i As Long
    Dim fieldNamesArray As Variant
    Dim isSort As Boolean

    If dc.Count > 0 Then
    If fieldNames <> "" Then
    fieldNamesArray = Split(fieldNames)
    Forall x In fieldNamesArray
    Set fieldSortArray(Strleft(x, ",")) = New SortArray(1, dc.Count, Cint(Strright(x, ",")))
    End Forall
    isSort = True
    Else
    isSort = False
    End If

    i = 0
    Redim NoteIDArray(1 To dc.Count)
    Set doc = dc.GetFirstDocument
    While Not (doc Is Nothing)
    i = i + 1
    NoteIDArray(i) = doc.NoteID
    If isSort Then
    Forall x In fieldNamesArray
    fieldSortArray(Strleft(x, ",")).element(i) = doc.GetItemValue(Strleft(x, ","))
    End Forall
    End If
    Set doc = dc.GetNextDocument(doc)
    Wend
    End If
    End Sub

    Private Function Comparator(value1 As Variant, value2 As Variant) As Single
    Dim max As Long
    Dim i As Long

    If Ubound(value1) > Ubound(value2) Then max = Ubound(value2) Else max = Ubound(value1)
    Comparator = 0
    For i = 0 To max
    If value1(i) > value2(i) Then
    Comparator = 1
    Exit For
    End If
    If value2(i) > value1(i) Then
    Comparator = -1
    Exit For
    End If
    Next
    If Comparator = 0 Then
    If Ubound(value1) > Ubound(value2) Then Comparator = 1
    If Ubound(value2) > Ubound(value1) Then Comparator = -1
    End If
    End Function

    Private Function ArrayComparator(i1 As Long, i2 As Long) As Single
    ArrayComparator = 0
    Forall x In fieldSortArray
    ArrayComparator = Comparator(x.element(i1), x.element(i2))
    ArrayComparator = ArrayComparator * x.order
    If ArrayComparator <> 0 Then Exit Forall
    End Forall
    End Function

    Sub Sort
    Dim i As Long, k As Long
    Dim LowerBound As Long
    Dim UpperBound As Long
    Dim TempNoteID As String*8
    Dim TempValue As Variant

    LowerBound = Lbound(NoteIDArray)
    UpperBound = Ubound(NoteIDArray)

    k = (UpperBound - LowerBound + 1) \ 2
    Do While k > 0
    For i = LowerBound To UpperBound - k
    If ArrayComparator(i, i + k) = 1 Then
    TempNoteID = NoteIDArray(i)
    NoteIDArray(i) = NoteIDArray(i + k)
    NoteIDArray(i + k) = TempNoteID
    Forall x In fieldSortArray
    TempValue = x.element(i)
    x.element(i) = x.element(i + k)
    x.element(i + k) = TempValue
    End Forall
    End If
    Next i

    For i = UpperBound - k To LowerBound Step -1
    If ArrayComparator(i, i + k) = 1 Then
    TempNoteID = NoteIDArray(i)
    NoteIDArray(i) = NoteIDArray(i + k)
    NoteIDArray(i + k) = TempNoteID
    Forall x In fieldSortArray
    TempValue = x.element(i)
    x.element(i) = x.element(i + k)
    x.element(i + k) = TempValue
    End Forall
    End If
    Next i
    k = k \ 2
    Loop
    End Sub
    End Class[/CODE]
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Использование</div></div><div class="sp-body"><div class="sp-content"><!--shcode--><pre><code class='ls'>Dim db As NotesDatabase
    Dim dc As NotesDocumentCollection
    Dim doc As NotesDocument
    Dim arr As NoteIDArray
    Dim i As Long
    ...
    'Здесь через пробел перечисляются поля по которым сортировать. Через запятую порядок сортировки. 1 - по убыванию, -1 - по возрастанию, 0 - не сортировать
    Set arr = New NoteIDArray(db, dc, "Поле1,1 Поле2,-1 Поле3,1")
    Call arr.Sort
    ...
    For i = Lbound(arr.NoteIDArray) To Ubound(arr.NoteIDArray)
    Set doc = db.GetDocumentByID(arr.NoteIDArray(i))
    ...
    Next[/CODE]
    Это для отчетов используется. Сортировку можно другую впихнуть. Меня улучшенным пузырьком устроила, т.к. время сортировки гораздо меньше времени построения отчета. И разница получается буквально в секунды, по сравнению с отчетом, который может строиться минуту или несколько.
    И направление сортировки задается несколько коряво, т.к. надо было срочно сделать. :)
     
Загрузка...

Поделиться этой страницей