Манипулирование данными в таблицах Google с помощью arrayformula и лямбда-помощников

Мне нужно решить довольно сложную ситуацию с помощью Google Таблиц. Я уже решил это очень неэлегантным способом, и мне нужна ваша помощь, чтобы понять, почему другие решения, которые я пробовал, не увенчались успехом, и, возможно, найти лучшее решение. Ссылку на лист я помещу в конце поста.

Вот сценарий:

Мои данные состоят из списка сотрудников (A2:A), столбца для центра затрат (B2:B) и столбца для каждого месяца (C2:N), содержащего процент вменения для этого сотрудника в этом месяце за этот центр затрат. Это позволяет мне распределять затраты на сотрудников по разным центрам затрат с помощью другого файла. Это означает, что один и тот же сотрудник может встречаться несколько раз, но с разными центрами затрат (например, имя сотрудника 1 в моих данных).

Дипенденте МВЗ 01.01.2024 02.01.2024 03.01.2024 04.01.2024 05.01.2024 06.01.2024 07.01.2024 08.01.2024 09.01.2024 10.01.2024 11.01.2024 12.01.2024 Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 10,00% 30,00% 90,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% Имя сотрудника1 0 - СООБЩЕНИЕ 90,00% 10,00% 100,00% 50,00% 0,00% 0,00% 0,00% 0,00% 0,00% 0,00% 0,00% 0,00% Имя сотрудника2 ВОА 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% Имя сотрудника3 САИ ПАЛЕРМО 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% Имя сотрудника4 0 - АММИНИСТРАЗИОН 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00% 100,00%

Исходные данные

Результат, который мне нужен, — это массив, в котором для каждой комбинации сотрудника и центра затрат должно быть 12 строк (по одной на каждый месяц) с процентом вменения. Мне нужен следующий вывод:

Месе Дипенденте CDC Импутация поколение 24 Имя сотрудника1 0 - СООБЩЕНИЕ 90,00% поколение 24 Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 10,00% поколение 24 Имя сотрудника2 ВОА 100,00% поколение 24 Имя сотрудника3 САИ ПАЛЕРМО 100,00% 24 февраля Имя сотрудника1 0 - СООБЩЕНИЕ 10,00% 24 февраля Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 30,00% 24 февраля Имя сотрудника2 ВОА 100,00% 24 февраля Имя сотрудника3 САИ ПАЛЕРМО 100,00% 24 марта Имя сотрудника1 0 - СООБЩЕНИЕ 100,00% 24 марта Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 90,00% 24 марта Имя сотрудника2 ВОА 100,00% 24 марта Имя сотрудника3 САИ ПАЛЕРМО 100,00% 24 апреля Имя сотрудника1 0 - СООБЩЕНИЕ 50,00% 24 апреля Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 100,00% ... ... ... ...

Желаемый результат

Чтобы получить этот результат, я использовал несколько именованных функций (да будет благословен Google за эту замечательную функцию):

Функция TUPLEGENERATION(сотрудник): она генерирует все строки для одного сотрудника для одного центра затрат. Это код, в котором ссылкой на сотрудника может быть любая ячейка в диапазоне A2:A:

=TOROW({
transpose(_MONTHS) \                                      //_MONTHS is a defined range just containing an array of months from january to december
transpose(split(rept(employee&"|";12);"|")) \             //this allows me to repeat 12 times the name of the employee, 1 time for each month
transpose(split(rept(offset(employee;0;1)&"|";12);"|")) \ //this does the same as above, but with the cost centre (its' the cell next to the employee, so I use offset)
transpose(offset(employee;0;2;1;12))})                    //this gets the 12 imputation values (next 12 columns)

выходные данные этой функции, примененные к первой строке данных, следующие: ВЫХОД а вот транспонированная версия, чтобы вам было лучше ее понять: ТРАНСПОНСИРОВАННЫЙ ВЫХОД я не включаю сюда вывод таблицы, так как он не очень важен

Функция MULTITUPLEGEN: она просто применяет BYROW к функции TUPLEGENERATION, поэтому вместо одной ячейки в качестве параметра требуется диапазон. Вот код:

=BYROW(range;TUPLEGENERATION)

вот результат, примененный к первым трем строкам моих данных

поколение 24 Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 10,00% 24 февраля Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 30,00% 24 марта Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 90,00% ... поколение 24 Имя сотрудника1 0 - СООБЩЕНИЕ 90,00% 24 февраля Имя сотрудника1 0 - СООБЩЕНИЕ 10,00% 24 марта Имя сотрудника1 0 - СООБЩЕНИЕ 100,00% ... поколение 24 Имя сотрудника2 ВОА 100,00% 24 февраля Имя сотрудника2 ВОА 100,00% 24 марта Имя сотрудника2 ВОА 100,00% ... поколение 24 Имя сотрудника3 САИ ПАЛЕРМО 100,00% 24 февраля Имя сотрудника3 САИ ПАЛЕРМО 100,00% 24 марта Имя сотрудника3 САИ ПАЛЕРМО 100,00% ... поколение 24 Имя сотрудника4 0 - АММИНИСТРАЗИОН 100,00% 24 февраля Имя сотрудника4 0 - АММИНИСТРАЗИОН 100,00% 24 марта Имя сотрудника4 0 - АММИНИСТРАЗИОН 100,00% ...

МУЛЬТИТУПЛЕГЕННЫЙ ВЫХОД

Функция MONTHGEN: здесь происходит волшебство. Он использует выходные данные MULTITUPLEGEN для извлечения данных за конкретный месяц для этого диапазона сотрудников. первый параметр — это число от 1 до 12, соответствующее месяцу, который вы хотите сгенерировать. второй параметр — это диапазон полномочий сотрудников, которые необходимо генерировать. Вот код:

=CHOOSECOLS(MULTITUPLEGEN(range);sequence(4;1;month*4-3;1))

и вот результат, примененный к первым трем строкам моих данных

24 марта Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 90,00% 24 марта Имя сотрудника1 0 - СООБЩЕНИЕ 100,00% 24 марта Имя сотрудника2 ВОА 100,00%

ВЫХОД МЕСЯЦА

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

Уродливая функция

=sort({MONTHGEN(1;attrib!A2:A4);MONTHGEN(2;attrib!A2:A4);MONTHGEN(3;attrib!A2:A4);MONTHGEN(4;attrib!A2:A4);
MONTHGEN(5;attrib!A2:A4);MONTHGEN(6;attrib!A2:A4);MONTHGEN(7;attrib!A2:A4);MONTHGEN(8;attrib!A2:A4);
MONTHGEN(9;attrib!A2:A4);MONTHGEN(10;attrib!A2:A4);MONTHGEN(11;attrib!A2:A4);MONTHGEN(12;attrib!A2:A4)})

вот результат, примененный к тем же трем строкам:

поколение 24 Имя сотрудника1 0 - СООБЩЕНИЕ 90,00% поколение 24 Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 10,00% поколение 24 Имя сотрудника2 ВОА 100,00% 24 февраля Имя сотрудника1 0 - СООБЩЕНИЕ 10,00% 24 февраля Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 30,00% 24 февраля Имя сотрудника2 ВОА 100,00% 24 марта Имя сотрудника1 0 - СООБЩЕНИЕ 100,00% 24 марта Имя сотрудника1 0 - СРЕДА ОБИТАНИЯ 90,00% 24 марта Имя сотрудника2 ВОА 100,00% 24 апреля Имя сотрудника1 0 - СООБЩЕНИЕ 50,00% ... ... ... ...

выход

Результат является желаемым, и в моей последней версии диапазон является статическим диапазоном, поэтому он вообще не отображается в формуле, но я действительно не могу смириться с тем, что мне пришлось вручную 12 раз объединять функцию с возрастающим числом. параметр, не имея возможности использовать ARRAYFORMULA или другие подобные функции.

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

Я потратил часы, пробуя разные подходы к проблеме, включая разные стартовые функции и манипулирование данными, но вот основные проблемы, с которыми я столкнулся:

  1. WRAPROWS — очень полезная функция, примененная к моей функции TUPLEGENERATION, но она принимает в качестве диапазона только одну строку. Он не может накладывать несколько диапазонов поверх другого, поэтому он бесполезен с функцией MULTITUPLEGEN, и я не смог выполнить итерацию с помощью ARRAYFORMULA или BYROW.

  2. VSTACK полезен, если вы вручную вставляете его в несколько выходных данных WRAPROWS(TUPLEGENERATION), но мне не удалось перебрать его с помощью BYROW или ARRAYFORMULA для генерации моего вывода.

  3. В общем, при повторении определенного диапазона я обнаружил, что довольно сложно расширить его динамически, генерируя больше строк в его середине. стартовый диапазон. Я пробовал большинство вспомогательных функций LAMBDA, таких как SCAN, MAKEARRAY, LET и т. д., но основная проблема заключается в том, что большинству из них разрешено возвращать только 1 строку за исходную итерацию, и попытка обойти это с помощью транспозиции и укладки просто не дает результатов. Это не работает из-за порядка выполнения, так как транспонирование происходит в неподходящее время, возвращая неверные данные. Признаюсь, я не особо долго погружался в MAKEARRAY, поэтому не могу исключить, что просто не использовал его в полной мере.

вот лист: https://docs.google.com/spreadsheets/d/e/2PACX-1vS7Vi43KDQigiBlAR9HnTsfK9TSo7PoSPTZZuys9GaczADUSXv_qY_uCSuwy7jeq3m9JGcqDACs_ywi/pubhtml

Заранее спасибо за помощь!

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
73
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете попробовать:

=let(Σ;A2:index(A:A;match(;0/(A:A<>""))); reduce(tocol(;1);C1:N1;lambda(a;c;vstack(a;hstack(wrapcols(c;rows(Σ);c);Σ;offset(Σ;;1);offset(Σ;;column(c)-1))))))

  • Настройте формулу в соответствии с диапазонами ваших листов.
  • Столбец вывода даты форматируется в произвольном формате mmm" "yyyy

большое спасибо, это работает, но чтобы правильно это понять, мне нужна помощь в нескольких вещах: 1) я впервые вижу синтаксис, который вы использовали в A2:X, где X - функция, и я не могу найти никакой документации ( я пропустил ключевое слово для его поиска). Я имею в виду, что X в нашем случае является последним элементом диапазона A:A, поэтому, на мой взгляд, вы пишете «A2:Empoyeename4», что для меня не имеет особого смысла (это какой-то синтаксис, который я никогда не использовал) 2) Некоторые другие части формулы для меня не имеют смысла (например, tocol(;1); возвращает ошибку, если я попытаюсь использовать ее за пределами этой формулы)

Francesco De Santis 23.05.2024 13:19

1, A2:index(A:A;match(;0/(A:A<>""))) соответствует A2:A6 для ваших тестовых данных. 2,tocol(;1) работает нормально только в сочетании с vstack. его цель здесь — предоставить нулевое значение в качестве заголовка уменьшения()

rockinfreakshow 23.05.2024 13:24
Ответ принят как подходящий

в принципе это просто:

=INDEX(SORT(SPLIT(TOCOL(C1:N1&"×"&A2:A6&"×"&B2:B6&"×"&C2:N6); "×")))

подача динамического диапазона будет:

=INDEX(LET(x; C2:INDEX(N:N; MAX(ROW(A:A)*(A:A<>""))); 
 SORT(SPLIT(TOCOL(OFFSET(x;-1;;1;)&"×"&OFFSET(x;;-2;;1)&"×"&OFFSET(x;;-1;;1)&"×"&x); "×"))))

и первый столбец вывода можно отформатировать либо внутри, с помощью кнопки 123:

или по формуле:

=QUERY(INDEX(LET(x; C2:INDEX(N:N; MAX(ROW(A:A)*(A:A<>""))); SORT(SPLIT(TOCOL(
 OFFSET(x;-1;;1;)&"×"&OFFSET(x;;-2;;1)&"×"&OFFSET(x;;-1;;1)&"×"&x); "×")))); 
 "format Col1 'mmm yyyy'"; )

подождите, вы говорите мне, что можете выполнить умножение массива (строка, представленная C1:N1, на имена, представленные A2:A6), просто используя оператор concat & ?

Francesco De Santis 23.05.2024 13:29

@FrancescoDeSantis да, почему бы и нет :) ответ обновлен

player0 23.05.2024 13:36

Другие вопросы по теме