Google Sheets — Немного про IMPORTRANGE()
Статья Михаила Смирнова, написанная для канала t.me/google_sheets
Чат канала: t.me/google_spreadsheets_chat
Другие статьи Миши, написанные для нашего канала: t.me/google_sheets/1203
Здравствуйте, товарищи!
По случаю радостного повода — гугловцы героически починили IMPORTRANGE(), пишем небольшую статью по теме этой функции.
Сейчас будем импортировать данные, фильтровать и подписывать, откуда они взялись.

Если кто не знает, IMPORTRANGE() (документация на функцию) достаёт из других таблиц данные и располагает их там, где прописана формула. Нужно это, например, для того, чтобы собрать однотипные данные с разных таблиц и в одном месте всё проанализировать.
У меня в таблице три листа: import, Финансовый Отдел, Инженерный Отдел. На 2-м и 3-м листах данные, на первый буду импортировать.
В реальной ситуации данные обычно импортируются из разных таблиц, Id'шники в функции импорта разные. Тут искусственный пример, всё происходит в рамках одной таблицы, Id'шники будут везде одинаковые − пусть это никого не смущает.
Данные
Случайным образом нагенерил данных два столбца по 10 строк: даты и суммы.
=ARRAYFORMULA(INT(RANDARRAY(10; 2) * {20\ 1000} + {TODAY()\ 500}))

Импортируем
Пробуем импортировать:
=IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "финансовый отдел!A:B")

Теперь объединим данные от двух импортов:
={
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Финансовый Отдел!A:B");
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Инженерный Отдел!A:B")
}

Поправим пару мелких неудобств:
- Заголовки повторяются
- Импортировались и пустые строки тоже, данные со второго импорта идут только после них
Заголовки можно было бы оставить в одном из импортов, но мы вынесем в отдельную строку, чтобы импорты были однотипные. Добавим фильтрацию с помощью QUERY() – в первом столбце должны быть значения (у вас могут быть другие критерии):
=QUERY(
{
"Дата"\ "Сумма";
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Финансовый Отдел!A2:B");
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Инженерный Отдел!A2:B")
};
"WHERE Col1 IS NOT NULL";
1
)

Теперь всё хорошо, можно работать.
Подписываем данные − откуда взялись
Иногда возникает желание в соседнем столбце иметь информацию, откуда конкретная строка взялась. Ниже несколько способов, как это можно реализовать.
Способ 1 − через QUERY
Добавляем заголовок "Источник", оборачиваем каждый импорт в QUERY(), где добавляем столбец с повторяющимся текстом:
=QUERY(
{
"Дата"\ "Сумма"\ "Источник";
QUERY(
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Финансовый Отдел!A2:B");
"SELECT Col1, Col2, 'Финансовый Отдел' LABEL 'Финансовый Отдел' ''";
);
QUERY(
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Инженерный Отдел!A2:B");
"SELECT Col1, Col2, 'Инженерный Отдел' LABEL 'Инженерный Отдел' ''";
)
};
"WHERE Col1 IS NOT NULL";
1
)

Плюсы:
- ✅ Относительно компактно
- ✅ Относительно просто для понимания
Минусы:
- ❌ Надо явно перечислять все столбцы в SELECT
- ❌ Подписи (название источника) в разных местах, хоть и рядом с каждым импортом. Если забыть её поменять при копипасте, всё будет работать, но можно и не понять, почему данные не импортируются (а они импортируются, у них просто подпись одинаковая).
Способ 2 − через схлопывание и 2D виртуальный диапазон
☠ Сразу скажу, способ не очень хороший, так как требует, чтобы в источниках было одинаковое количество строк. Обычно это не так.
Что за схлопывания (TRANSPOSE(QUERY(TRANSPOSE(...)))), можно изучить здесь. 2D виртуальный диапазон − это столбцы с импортированными данными {...\ ...} (внимание на \) и строка с подписями {"Финансовый Отдел"\ "Инженерный Отдел"}:
=QUERY(
{
"Дата"\ "Сумма"\ "Источник";
ARRAYFORMULA(
SPLIT(
FLATTEN(TRANSPOSE(
{
TRANSPOSE(QUERY(TRANSPOSE(
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Финансовый Отдел!A2:B") & "♥️"
);; 10^7))\
TRANSPOSE(QUERY(TRANSPOSE(
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Инженерный Отдел!A2:B") & "♥️"
);; 10^7))
} & " " & {"Финансовый Отдел"\ "Инженерный Отдел"}
));
"♥️ ";;
)
)
};
"WHERE Col1 IS NOT NULL";
1
)
Результат тот же, картинки не будет.
Плюсы:
- ✅ Более универсальная конструкция. Нет никаких зависимостей от количества столбцов и строк. (На самом деле есть: в заголовках, но это один раз перечислить).
- ✅ Все подписи в одном месте. Если забыть добавить подпись для нового импорта сразу будет ошибка.
Минусы:
- ❌ Источники должны содержать одинаковое количество строк. Эту проблему можно обойти через добавление столбца с источником через QUERY() (как в Способе 1), но второй плюс этого способа потеряется.
- ❌ Сложная для понимания конструкция
- ❌ Много преобразований строк, что требует ресурсов
Короче, способ не шибко хороший. Для повышения общего уровня культуры. Схлопывания и ARRAYFORMULA() на 2D диапазонах − крайне полезные вещи, часто пригождаются.
Способ 3 – через дополнительные импорты
Можно добавить столбцы с названием источника через повторение значения с помощью IF(SEQUENCE(); ...). Но для этого потребуются дополнительные импорты, с помощью которых мы узнаем количество строк в каждой таблице:
=QUERY(
{
"Дата"\ "Сумма"\ "Источник";
{
{
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Финансовый Отдел!A2:B");
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Инженерный Отдел!A2:B")
}\
ARRAYFORMULA(
{
IF(SEQUENCE(ROWS(IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Финансовый Отдел!A2:A"))); "Финансовый Отдел");
IF(SEQUENCE(ROWS(IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Инженерный Отдел!A2:A"))); "Инженерный Отдел")
}
)
}
};
"WHERE Col1 IS NOT NULL";
1
)
Результат тот же.
Плюсы:
- ✅ Можно навставлять ссылок на конкретные строки
- ✅ Не нужно перечислять колонки
Минусы:
- ❌ Импортов в два раза больше (хоть мы и не всё повторно импортируем, а только первую колонку) из-за того, что надо знать количество импортированных строк.
Добавляем ссылки на источник
Способ 3 хорош для добавления ссылок на источник.
У нас есть ссылка на лист (вы её видите в браузере):
https://docs.google.com/spreadsheets/d/{SpreadsheetId}/edit#gid={SheetId}
- {SpreadsheetId} − Id таблицы
- {SheetId} − Id листа (да, надо пойти и посмотреть)
Если к ней добавить &range={range}, где {range} – это диапазон на листе, получится ссылка на конкретный диапазон (он будет выбран при открытии таблицы):
https://docs.google.com/spreadsheets/d/{SpreadsheetId}/edit#gid={SheetId}&range={range}
Мы для простоты будем добавлять ссылки на колонку A:A соответствующей строки:
=QUERY(
{
"Дата"\ "Сумма"\ "Источник";
{
{
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Финансовый Отдел!A2:B");
IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Инженерный Отдел!A2:B")
}\
ARRAYFORMULA(
"https://docs.google.com/spreadsheets/d/18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys/edit#"
& {
"gid=1424146655&range=A" & SEQUENCE(ROWS(IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Финансовый Отдел!A2:A")); 1; 2);
"gid=1978378908&range=A" & SEQUENCE(ROWS(IMPORTRANGE("18bnna1mIbuzZtwOzI4GLoXnlZTjScQ9I4lma-bHX1Ys"; "Инженерный Отдел!A2:A")); 1; 2)
}
)
}
};
"WHERE Col1 IS NOT NULL";
1
)

С данными что-то не так? Нажимаем на ссылку и смотрим в источнике, может, правим.
Заключение
Выбирайте способ, какой больше нравится. Или придумывайте свои, и делитесь с товарищами в чате, будем рады.
Если готовить ссылки и подписи в источнике, жить будет гораздо проще: достаточно будет импортировать и отфильтровывать пустые (то, что мы в самом начале делали).
На этом всё. Спасибо за внимание.
Ссылки
Google Sheets Functions
- IMPORTRANGE() — документация на функцию
- QUERY() — документация на функцию
- TRANSPOSE() — документация на функцию
- SEQUENCE() — документация на функцию
Хитрые техники
- Повторяем значения необходимое число раз
- Примеры, объяснения и картинки про горизонтальные и вертикальные схлопывания с помощью QUERY() и TRANSPOSE().
Статья Михаила Смирнова, написанная для канала t.me/google_sheets
Чат канала: t.me/google_spreadsheets_chat
Другие статьи Миши, написанные для нашего канала: t.me/google_sheets/1203