У меня есть таблица из 155К записей. Я могу прокрутить только 65K записей в поле со списком формы, имеющей источник записей с запросом или sql, выбрав три поля из этой таблицы. Почему он не перечисляет все 155K записей, даже если запрос, который я использую в качестве источника записей, показывает все записи вне формы.
получить 65K записей, перечисленных только в поле со списком, из таблицы из 155K записей
Ответы (10)
возможно, индекс элемента является 16-битным целым числом
Лучше спросить, действительно ли вы ожидаете, что пользователь прокрутит 155 тысяч элементов в поле со списком?
Самый простой подход - назначить поле со списком Rowsource только после того, как вы введете в него несколько символов. Вы должны сделать это в событии OnChange поля со списком:
Dim strRowSource As String
strRowSource = "SELECT MyID, MyField FROM MyTable"
If Len(Me!cmbMyCombo.Text)=3 Then
strRowSource = strRowSource & " WHERE MyField Like '"
strRowSource = strRowSource & Me!cmbMyCombo.Text
strRowSource = strRowSource & "*'"
Me!cmbMyCombo.RowSource = strRowSource
Me!cmbMyCombo.DropDown
End If
Когда вы вводите текст в поле со списком, ничего не происходит до тех пор, пока вы не наберете 3 символа (или 2, или 4, или что-то еще, что подходит для фильтрации раскрывающегося списка до количества записей, удобного для человека), и в это время назначается источник строк ( и, если хотите, вы можете раскрыть список в этом месте, чтобы сделать его более удобным для пользователя). С этого момента он будет работать как любое обычное поле со списком.
Если вам нужно использовать одно и то же поле со списком для отображения данных в записях, которые не были введены, вы можете сделать источник строк по умолчанию для поля со списком:
PARAMETERS [Forms]![MyForm]![MyField] Text ( 255 );
SELECT MyID, MyField FROM MyTable WHERE MyField = [Forms]![MyForm]![MyField];"
Затем в своем событии OnChange вы должны сделать это:
Dim strRowSource As String
strRowSource = "PARAMETERS [Forms]![MyForm]![MyField] Long; "
strRowSource = strRowSource & "SELECT MyID, MyField FROM MyTable "
strRowSource = strRowSource & "WHERE MyField = [Forms]![MyForm]![MyID]"
strRowSource = strRowSource & "UNION SELECT MyID, MyField FROM MyTable"
If Len(Me!cmbMyCombo.Text)=3 Then
strRowSource = strRowSource & " WHERE MyField Like '"
strRowSource = strRowSource & Me!cmbMyCombo.Text
strRowSource = strRowSource & "*'"
Me!cmbMyCombo.RowSource = strRowSource
Me!cmbMyCombo.DropDown
End If
Затем в событии OnCurrent формы вы должны сделать это:
Dim strRowSource As String
strRowSource = "PARAMETERS [Forms]![MyForm]![MyField] Text ( 255 ); "
strRowSource = strRowSource & "SELECT MyID, MyField FROM MyTable "
strRowSource = strRowSource & "WHERE MyField = [Forms]![MyForm]![MyField]"
Me!cmbMyCombo.RowSource = strRowSource
Это позволяет убедиться, что любое значение, уже присвоенное полю, к которому привязано поле со списком, по-прежнему будет отображаться. Если у вас есть пустой RowSource, это не сработает, поэтому ссылка на текущее значение формы для этого поля и ОБЪЕДИНЕНИЕ его с отфильтрованным списком.
Другой человек согласен с тем, что это был бы безумный способ предоставить пользователю доступ к этим данным. Никто и никогда не захочет разбирать более 100 тысяч записей за один раз. Я бы предоставил способ заранее отфильтровать записи, чтобы в них были представлены только те, которые представляют интерес в данный момент.
Итак, что вы действительно ищете, это скорее функция «Автозаполнение», как в интернет-браузерах? Когда вы говорите поле со списком, все рисуют раскрывающийся список, в котором пользователь выбирает элемент - возможно, вы захотите уточнить свой вопрос.
Попробуйте что-нибудь вроде поля со списком с постепенным заполнением. например как работает поиск по тегам в Stack Overflow или как работает Google Suggest. 65k - это достаточно хороший предел для поля со списком. Обычному пользователю будет сложно выбрать даже из 65 вещей.
Как правило, когда вы сталкиваетесь с жестко заданным ограничением для общего и широко используемого компонента, такого как поле со списком, пора пересмотреть свой подход. Поле со списком не предназначено для вашего варианта использования и его недостаточно. Сделайте пару шагов назад от своего проекта и переоцените свой пользовательский интерфейс. Возможно, ListView или сетка отфильтрованных данных были бы более подходящими.
65536 - это действительно ограничение на количество элементов поля со списком.
Я бы посоветовал использовать текстовое поле с кнопкой поиска, чтобы найти кого-нибудь из списка, а не использовать поле со списком в этом случае.
В качестве альтернативы вы можете загружать элементы, динамически зависящие от вставленного текста.
Вы также можете попытаться выполнить предварительную фильтрацию поля со списком с помощью ранее введенного значения в форме, чтобы получить количество возвращенных записей ниже максимально допустимого. Например, если в вашей таблице было 100000 имен и адресов, вы бы попросили пользователя ввести (перед использованием поля со списком) почтовый индекс или состояние, которое будет использоваться для фильтрации количества записей, возвращаемых вашим запросом RecordSource поля со списком.
@ Стивен А. Лоу и amdfan: знаете ли вы, что такое combobox и почему оно называется поле со списком? Это текстовое поле в сочетании со списком. Вы вводите текст, и в списке отображаются первые записи, соответствующие вашему тексту.
Так что, думаю, это законный вопрос.
Нетрудно создать комбинацию текстового поля и поля списка, где список запрашивается в событии изменения текстового поля, постепенно сужая выбранные элементы. Это будет означать, что ваши пользователи по-прежнему могут видеть список имен, а не догадываться, но гораздо более короткий и релевантный список.
Вот пример SQL для RowSource такого списка:
SELECT tp.PersonKey,
tp.Surname & ", " & tp.Forename AS PersonName
FROM tblPersons tp
WHERE tp.Surname
LIKE Forms!MyForm!txtSurname.Text
ORDER BY tp.Surname, tp.Forename
Обратите внимание на использование свойства Text текстового поля, это гарантирует, что используется текущее содержимое текстового поля, но это также означает, что текстовое поле не может быть запрошено, за исключением случаев, когда txtSurname имеет фокус, что нормально, потому что запрос должен выполняться только в случае изменения txtSurname.
Сложно использовать в реальном мире, combobox хранит 155 тыс. Записей, я думаю, если изменить его на [...] кнопку просмотра или другой элемент управления, мне будет проще использовать этот способ.
Если у вас есть массивный список, я бы заменил его таблицей (или формой) внутри объекта подчиненной формы. Поля со списком и список имеют ограничение в 65 536 объектов, и они загружаются медленно по сравнению с таблицей, запросом или формой в подчиненной форме. У меня 100 000 записей в одной таблице, и она загружается в мгновение ока. Он также очень легко прокручивается, намного быстрее, чем список, а это означает, что вам не нужно сужать выбор. У меня обычно есть простое поле поиска под моей подчиненной формой.
Это немного сложнее, потому что вам нужно ссылаться на дочернюю форму из родительской формы и наоборот, но довольно легко преобразовать весь код вашего поля со списком / списком в код подчиненной формы. например если вы хотите найти соответствующую запись в основной форме, когда вы щелкаете запись в подчиненной форме: -
Private Sub POLICY_NO_Click()
Set Me.Parent.Recordset = CurrentDb.OpenRecordset("qryHPolicy")
Me.Parent.Recordset.FindFirst "[POLICY_NO]=" & Me.POLICY_NO & ""
End Sub
или установите для подчиненной формы тот же источник записей, что и для основной формы: -
Forms(Me_FormTo).Form.RecordSource = Me_RecSource
Forms(Me_FormTo).Combo6.Form.RecordSource = Me_RecSource
Вы можете заставить новую подчиненную форму выглядеть и работать точно так же, как список, поэтому определенно стоит попробовать, когда у вас более 64 КБ записей.