«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Google Sheets: как построить SUMIFS за несколько часов

Google Sheets: как построить SUMIFS за несколько часов

Опубликовано 8 ноября 2024 г.
Просматривать:425

Google Sheets: How to Build a SUMIFS for Hours

Всем привет! Сегодня я хочу поделиться суперполезным скриптом, который я создал для решения распространенной проблемы в повседневной жизни.

Если вы когда-нибудь пробовали суммировать «длительность» в Google Таблицах, вы могли заметить, что формулы СУММЕСЛИ и СУММЕСЛИ не работают для суммирования продолжительности событий или продуктов на основе определенных критериев. Это может быть препятствием в зависимости от типа расчета, который вам нужно выполнить. Но не волнуйтесь! Google Таблицы позволяют создавать сценарии на JavaScript и использовать их в качестве пользовательских формул.

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

Следует отметить, что пользовательские формулы не возвращают значения, которые можно вычислить программой напрямую. Чтобы обойти эту проблему, вы можете обернуть результат функцией =VALUE(). Затем просто примените соответствующее форматирование к типу данных — в нашем случае «длительность». Готовы ознакомиться со сценарием?

Создание общих данных для тестирования

Прежде всего, давайте сгенерируем данные для проверки формулы. Для этого я использовал наш друг GPT.

Заголовок Продолжительность Категория Статус
Марсианин 01:00:00 Фильм Просмотрел
Интерстеллар 02:49:00 Фильм Просмотрел
Джон Уик 01:30:00 Фильм Просмотрел
Мстители: Финал 03:00:00 Фильм Хочу посмотреть
Очень странные дела 00:45:00 Ряд Смотрю
Ведьмак 01:00:01 Ряд Смотрю
Мандалорец 00:40:00 Ряд Смотрю
Во все тяжкие 00:50:00 Ряд Просмотрел
Ограбление денег 00:55:00 Ряд Хочу посмотреть
Игра престолов 01:10:00 Ряд Хочу посмотреть

Скрипт

Я старался все задокументировать как можно лучше. Я решил разбить его на более мелкие функции и использовать что-то более декларативное, чтобы повысить ясность кода.

function allAreArrays(...arrays) {
  return arrays.every(Array.isArray);
}

function allArraysHaveSameLength(...arrays) {
  const lengths = arrays.map((arr) => arr.length);
  return lengths.every((val) => val === lengths[0]);
}

function convertHMSToSeconds(hms) {
  // Breaks the string in HH:MM:SS format into parts
  const parts = String(hms).split(":");

  // Converts the parts into integers
  const [hours, minutes, seconds] = parts;

  // Converts hours and minutes into seconds and adds the seconds
  const totalSeconds =
    Number(hours) * 3600   Number(minutes) * 60   Number(seconds);

  return Number(totalSeconds);
}

function convertSecondsToHMS(seconds) {
  // Calculates the number of hours, minutes, and seconds
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const remainingSeconds = seconds % 60;

  // Adds a leading zero to ensure it always has two digits
  const hourFormat = String(hours).padStart(2, "0");
  const minuteFormat = String(minutes).padStart(2, "0");
  const secondFormat = String(remainingSeconds).padStart(2, "0");

  // Returns the HH:MM:SS format
  return `${hourFormat}:${minuteFormat}:${secondFormat}`;
}

/**
 * Sums hours based on a criterion.
 *
 * @param {string[]} sum_range - Set of time intervals in HH:MM:SS format.
 * @param {number[]} criteria_range - Set of criteria corresponding to the time intervals.
 * @param {number} criterion - The criterion for which hours should be summed.
 * @returns {string} Sum of the passed durations, or an error message.
 */
function sumHoursIf(sum_range, criteria_range, criterion) {
  if (!allAreArrays(sum_range, criteria_range))
    return "Pass the intervals for the calculation!";

  if (!allArraysHaveSameLength(sum_range, criteria_range))
    return "Intervals must be the same size";

  // Filters the time intervals for the specific criterion
  const hoursToSum = sum_range.filter(
    (row, index) =>
      String(criteria_range[index]).trim() == String(criterion).trim()
  );

  // Converts the filtered hours to seconds
  const hoursInSeconds = hoursToSum.map((n) => convertHMSToSeconds(n));

  // Sums all the seconds
  const sumOfSeconds = hoursInSeconds.reduce((accumulator, currentValue) => {
    return accumulator   currentValue;
  }, 0);

  // Converts the total seconds back to HH:MM:SS format
  return convertSecondsToHMS(sumOfSeconds);
}

/**
 * Sums hours based on criteria.
 *
 * @param {string[]} sum_range - Set of time intervals in HH:MM:SS format.
 * @param {number[]} criteria_range1 - First set of criteria corresponding to the time intervals.
 * @param {number} criterion1 - The first criterion for which hours should be summed.
 * @param {string[]} criteria_range2 - Second set of criteria corresponding to the time intervals.
 * @param {string} criterion2 - The second criterion for which hours should be summed.
 * @returns {string} Sum of the passed durations, or an error message.
 */
function sumHoursIf2(
  sum_range,
  criteria_range1,
  criterion1,
  criteria_range2,
  criterion2
) {
  if (
    !allAreArrays(
      sum_range,
      criteria_range1,
      criteria_range2
    )
  )
    return "Pass the intervals for the calculation!";

  if (
    !allArraysHaveSameLength(
      sum_range,
      criteria_range1,
      criteria_range2
    )
  )
    return "Intervals must be the same size";

  // Filters the time intervals for the passed criteria
  const hoursToSum = sum_range.filter(
    (row, index) =>
      String(criteria_range1[index]) == String(criterion1).trim() &&
      String(criteria_range2[index]).trim() === String(criterion2).trim()
  );

  // Converts the filtered hours to seconds
  const hoursInSeconds = hoursToSum.map((n) => convertHMSToSeconds(n));

  // Sums all the seconds
  const sumOfSeconds = hoursInSeconds.reduce((accumulator, currentValue) => {
    return accumulator   currentValue;
  }, 0);

  // Converts the total seconds back to HH:MM:SS format
  return convertSecondsToHMS(sumOfSeconds);
}

Как использовать?

Критерии могут быть текстовыми или цифровыми, но часы должны быть отформатированы как «Обычный текст». Перейдите к скрипту приложения, вставьте его и нажмите «CTRL S». Сделанный. Чтобы использовать ее, нужно использовать тот же процесс, что и нативную формулу.

После применения формулы мы можем снова рассматривать ее как тип, который понимает программа, используя VALUE; ваш код должен выглядеть так:

=VALUE(sumHoursIf2($C$2:$C$11;$D$2:$D$11;C$14;$E$2:$E$11;$B15))

Если все получилось, то это должен быть ваш результат:

Категория Фильм Серия
Ассистидо 5:19:00 0:50:00
Помощь 0:00:00 2:25:01
Вопрос помощи 3:00:00 2:05:00

Просто совет, надеюсь, вам понравилось, и если у вас есть предложения, оставляйте их в комментариях. Ваше здоровье.

Исходное сообщение: https://dev.to/casewinter/como-somar-horas-no-google-sheets-usando-criterios-para-filtrar-linhas-364p

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/casewinter/google-sheets-how-to-build-a-sumifs-for-hours-16ee?1. В случае нарушения прав обращайтесь по адресу [email protected]. удалить его
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3