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

  • Автор темы LuMee
  • Дата начала
L

LuMee

Данное решение не претендует на сильно большую практическую ценность, однако может быть кому-то пригодится. Представляет оно собой простеньку библиотечку для сортировки массивов, которую я лично использую при создании отчетов.
Библиотека включает в себя такие компоненты:
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]
В общем, вот, выставляю на суд общественности :)
 
A

Akupaka

Всем привет!

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

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

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


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

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
Ну идея такая.
Можно получить notesView.AllEntries. Коллекция будет отсортированнная.
Дальше циклом по твоим документам. Получаем энтри с помощью GetEntry. У энтри делаем GetPosition. А дальше понятно.


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

Akupaka

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

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

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
в навигаторе точно получалось... мне вот через позицию не понравилась мысля (первое о чем подумал сам), т.к. оно возвращает текстовую фикню, через разделитель...
А что в этом такого? Зато быстро, наверное, будет. Через нафигатор медленно. :blink:
В принципе вручную данные отсортировать.

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

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

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

Akupaka

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

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

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

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

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 980
611
BIT
427
сортировка не имеющая (относительно) ограничения в 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]
 
A

Akupaka

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

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
см.
Плохой метод. В конструкторе идет перегон коллекции в массив документов, если я правильно понял.
Код:
For i%=0 To DC
Set Docs(i%).doc = Coll.GetNthDocument(i%+1)
Это жрет очень много памяти. Я от такого отказался.
Лучший метод, по-моему, создать массив NoteID и дергать документ из базы каждый раз. Достаточно быстро и не жрет памяти.
 
A

Akupaka

см.
очень интересный пример, спасибо

Плохой метод. В конструкторе идет перегон коллекции в массив документов, если я правильно понял.
Код:
For i%=0 To DC
Set Docs(i%).doc = Coll.GetNthDocument(i%+1)
Это жрет очень много памяти. Я от такого отказался.
Лучший метод, по-моему, создать массив NoteID и дергать документ из базы каждый раз. Достаточно быстро и не жрет памяти.
возможно не оптимизированный, но не значит плохой :)
где-то я встречал подобную рекомендацию - хранить массив NoteID, но кто-нить может сказать, на сколько это увеличивает число операций считывания с диска, и на сколько это лучше хранения всех доков в памяти?
причем, эта рекомендация касается только очень больших массивов документов... 100 документов, к примеру, уже очень большой массив? :)
 

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
возможно не оптимизированный, но не значит плохой wink.gif
где-то я встречал подобную рекомендацию - хранить массив NoteID, но кто-нить может сказать, на сколько это увеличивает число операций считывания с диска, и на сколько это лучше хранения всех доков в памяти?
причем, эта рекомендация касается только очень больших массивов документов... 100 документов, к примеру, уже очень большой массив? smile.gif
Ну так проверь. С графиками. Пару часов займет. :)
Только сейчас запустил. Почти 9000 документов. Память начала утекать как вода сквозь пальцы. Физическая доступная практически кончилась. Своп вырос в два раза. С около 600 метров до 1 Гб. :)
Если делать через массив NoteID, то память практически не расходуется. За время построения около 30 метров ушло.
 
A

Akupaka

давай по порядку :)
плохой способ перечисления доков через Coll.GetNthDocument() - согласен, лучше getFirst/getNext

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

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

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

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
объекты доков в памяти - физическая доступная, это сколько? smile.gif на сколько ощущается разница в использовании диска между все доки в памяти и обращения к каждому отдельному? т.е. в одном случае гоняем своп, в другом - тащим доки...
Свободно было 70 Мб. По мере построения она уменьшалась, своп рос. Обращение к жд не мерил, т.к. жд на сервере. :)
Локально сейчас некогда тестировать.

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

в любом случае, для того, чтобы получить массив NoteID, нам придется перебрать коллекцию, потом провести сравнение документов, а значит выполнить операции по считыванию с диска множество раз, т.е. преимущество использовании диска или памяти пока еще не явно...
В случае с жд не забываем про кэширование. Так что не всё так просто.
 

duchan

Green Team
20.09.2006
128
11
BIT
228
Medevic, дык, ёлы-палы.... ну переделай код с получения из массива док-тов, на хранения NoteID. в данном случае это был пример, который КАЖДЫЙ может переделать под свои потребности...

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

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

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
дык, ёлы-палы.... ну переделай код с получения из массива док-тов, на хранения NoteID. в данном случае это был пример, который КАЖДЫЙ может переделать под свои потребности...
Ты дал пример, а я прокомментировал его как мне видится со своей колокольни. Что в этом плохого?

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

Akupaka

кеширование - все та же память, так что, есть ли разница? ;) шучу


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

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

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
можно попробовать доработать данный алгоритм таким образом, чтобы при формировании массива NoteID параллельно формировался массив параметров, которые позволили бы провести сравнение документов... тогда, в принципе, можно предположить, что мы получим некую "середину" в использовании памяти и диска... хз smile.gif
У меня так и сделано, оказывается. Вот мозги работали когда-то. :)
Если интересно, могу выложить свой класс.
 

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
<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]
Это для отчетов используется. Сортировку можно другую впихнуть. Меня улучшенным пузырьком устроила, т.к. время сортировки гораздо меньше времени построения отчета. И разница получается буквально в секунды, по сравнению с отчетом, который может строиться минуту или несколько.
И направление сортировки задается несколько коряво, т.к. надо было срочно сделать. :)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!