A1sCode библиотека 1С

A1sQ.PagedUnload

Назначение: отдать страницу данных и метаданные постраничной навигации из произвольного SELECT‑запроса.
Возвращает структуру: { Data: ТаблицаЗначений; HasMore: Булево; Total: Число }.

Сигнатура

Function PagedUnload(QueryText, PageSize, PageNumber, Value1 = Undefined, Value2 = Undefined, Value3 = Undefined, Value4 = Undefined, Value5 = Undefined, Value6 = Undefined, Value7 = Undefined, Value8 = Undefined) Export

Как работает (по исходному коду)

Result = New Structure;
	Result.Insert("Data", New ValueTable);
	Result.Insert("HasMore", False);
	Result.Insert("Total", 0);
	
	Try
		// Сначала получаем общее количество
		CountQuery = StrReplace(Upper(QueryText), "ВЫБРАТЬ", "ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Total ИЗ (ВЫБРАТЬ") + ") AS CountQuery";
		TotalCount = ValueQ(CountQuery, 0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8);
		Result.Total = TotalCount;
		
		// Вычисляем ПРОПУСТИТЬ и ПЕРВЫЕ
		SkipCount = (PageNumber - 1) * PageSize;
		TopCount = PageSize;
		
		// Модифицируем основной запрос
		PagedQueryText = QueryText;
		If StrFind(Upper(QueryText), "УПОРЯДОЧИТЬ ПО") = 0 Then
			PagedQueryText = PagedQueryText + " УПОРЯДОЧИТЬ ПО 1"; // Добавляем сортировку, если нет
		EndIf;
		
		// Добавляем ПРОПУСТИТЬ и ПЕРВЫЕ через подзапрос
		PagedQueryText = "ВЫБРАТЬ ПЕРВЫЕ " + TopCount + " * ИЗ (" + PagedQueryText + ") T";
		If SkipCount > 0 Then
			PagedQueryText = StrReplace(PagedQueryText, "ВЫБРАТЬ ПЕРВЫЕ", "ВЫБРАТЬ ПРОПУСТИТЬ " + SkipCount + " ПЕРВЫЕ");
		EndIf;
		
		// Выполняем запрос страницы
		Result.Data = Unload(PagedQueryText, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8);
		Result.HasMore = (SkipCount + PageSize) < TotalCount;
		
	Except
		A1sS.Print("PagedUnload error: " + ErrorDescription());
	EndTry;
	
	Return Result;
Важно: пагинация корректна только при детерминированной сортировке. Добавляйте в исходный QueryText явный УПОРЯДОЧИТЬ ПО, иначе порядок строк между страницами может «плясать».

Параметры

  • QueryText — текст запроса ВЫБРАТЬ ... (ожидается именно SELECT).
  • PageSize — размер страницы (сколько строк вернуть).
  • PageNumber — номер страницы, начиная с 1.
  • Value1..Value8 — значения параметров запроса, если в QueryText используются &Имя.

Возвращает

Структуру { Data, HasMore, Total }, где:

  • Data — ТаблицаЗначений текущей страницы;
  • HasMore — Истина, если после текущей страницы ещё есть данные;
  • Total — общее количество строк, рассчитанное отдельным подзапросом КОЛИЧЕСТВО(*).

Примеры

1) Базовая пагинация со стабильной сортировкой

Text = "
|ВЫБРАТЬ
|  Док.Ссылка, Док.Номер, Док.Дата, Док.Сумма
|ИЗ Документ.РеализацияТоваровУслуг КАК Док
|ГДЕ Док.Дата МЕЖДУ &D1 И &D2
|УПОРЯДОЧИТЬ ПО Док.Дата УБЫВ, Док.Номер УБЫВ";

Page = A1sQ.PagedUnload(Text, 50, 1, НачалоПериода, КонецПериода);
ТЗ = Page.Data; // 50 строк
Если Page.HasMore Тогда Сообщить("Всего строк: " + Строка(Page.Total)); КонецЕсли;

2) Перейти на страницу N

PageN = A1sQ.PagedUnload(Text, 50, N, НачалоПериода, КонецПериода);
Если НЕ PageN.HasMore Тогда Сообщить("Это последняя страница."); КонецЕсли;

Нюансы и ограничения

✅ Простая API: отдаёт и данные, и Total, и HasMore
✅ Работает с параметризованными запросами (до 8 параметров)
❗ Исходный запрос должен быть SELECT (начинаться с «ВЫБРАТЬ»)
❗ Корректность пагинации требует явной сортировки (УПОРЯДОЧИТЬ ПО)
❗ Для расчёта Total формируется обёртка с КОЛИЧЕСТВО(*) поверх исходного текста;
   имейте в виду, что внутренняя реализация использует Upper(QueryText) —
   если в исходном тексте есть литералы, чувствительные к регистру, результат Total может отличаться
❗ При ошибке выполнения вернёт пустую таблицу, HasMore=Ложь, Total=0 и напишет в лог «PagedUnload error: ...»
  • Unload — выгружает весь результат без пагинации.
  • CountQ — быстрое количество строк.
  • ExistsQ — проверка наличия записей.