1. Делаете служебный лист c названиями всех имеющихся листов (городов) в Вашей таблице.
Можете сделать это вручную, можете скриптом, он достаточно простой.
Можно даже запускать такой скрипт при открытии таблицы автоматически, если предполагается изменение количества страниц.
2. Собираете данные со всех листов, но в первую колонку
вставляете название листа.
Делаетеся это такой формулой:
=REDUCE({"Город"\"Продукт"\"Дата"\"Сумма"\"Менеджер"};
tocol('Города'!A2:A;1);
LAMBDA(acc;city;
VSTACK(acc;
BYROW(INDIRECT(city&"!A2:D");LAMBDA(_row;{city\_row})))
)
)
Reduce - сводит воедино данные по страницам (городам в Вашем случае). lambda - составная часть этой функции.
TOCOL cо вторым параметром 1 используется в данном случае чтоб убрать пустые строки, так как количество городов неизвестно и мы используем открытый диапазон A2:A.
VSTACK - объединяет массивы. В данном случае - массив acc, результат предыдущих итераций reduce, с текущим.
BYROW - используется для построчной обработки данных. В данном случае - для формирования строки из названия текущего города (city из текущей итерации reduce) и каждой строки со страницы текущего города.
3. Эту формулу оборачиваете в нужный вам QUERY, где в том числе фильтруете пустые строки.
Вот ваш QUERY:
А вот так он будет выглядеть, когда в качестве "входящего" диапазона используется формула из п2.
=QUERY(
REDUCE(...
);
"SELECT ..")