Позднее Ctrl + ↑

Дата в формате «год-номер недели», в Power Query

В отчете Power Bi, требуется добавить столбец с датой в формате «год-номер недели»

Определяем номер недели, неделя начинается с понедельника

Text.From(Date.WeekOfYear([date], Day.Monday))

Определяем год

Date.Year([date])

Не забываем преобразовать в текст и объединить

Text.From(Date.Year([date])) & "-" & Text.From(Date.WeekOfYear([date], Day.Monday))
Результат выполнения будет «год-неделя», но однозначные недели, будут из одного символа, в дальнейшем сортировка собьется.

Добавим, условие если неделя однозначная, добавь впереди ноль, получаем итоговая формула:

Text.From(Date.Year([date])) & "-" & Text.PadStart(Text.From(Date.WeekOfYear([date], Day.Monday)), 2, "0")
Столбец оставляет вида «текст», сортировка не будет сбиваться.

Это быстрое решение, когда не нужно добавлять готовый календарь.

Преобразование даты без форматирования в формат даты в Power Query

При подготовки отчета в PowerBi выяснилось что даты находятся в столбце с форматом: день, месяц и год без разделителей

Первый день может быть однозначным и двухзначным, например, 7 февраля и 22 февраля.

При загрузке в PowerBi даты выглядят как числа

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

Попробуем сделать сделать столбцы день, месяц и год, а потом их объединить в даты

Заменяем тип столбца на текстовый, чтобы корректно работать с текстовыми функциями, для этого нажимаем на стрелочку и выбираем формат «текст»

Выделяем год

Дополнительный столбец с кодом года

=Text.End([дата],4)
Берем последние четыре символа, это и будет год.

Выделяем месяц

Дополнительный столбец с кодом месяца

=Text.Start(Text.End([дата],6),2)
Берем последние шесть символов, и отрезаем первые два — это и будет месяц.

Выделяем месяц

Дополнительный столбец с кодом дня

=if Text.Length([дата]) = 8 then  Text.Start([дата],2) else Text.Start([дата],1)
Если в дате 8 символов возьми первые два, иначе возьми первый символ — это будет день
Сортируем день, месяц, год
Выделяем столбцы и нажимаем кнопку «объединить»
Выбираем символ объединения «точка», и наименование нового столбца
Получаем объединенный столбец дата в формате «текст»
Преобразовываем столбец в формат дата

Календарь для сквозной аналитики в гугл таблице

Сделаем календарь для сквозной аналитики от даты начала day_start до даты окончания day_end
Вместо даты начала и окончания можно вставить минимальную и максимальную даты в вашем отчете

Date — дата

=ARRAYFORMULA(ROW(INDIRECT("A"&DATEVALUE(day_start)&":A"&DATEVALUE(day_end))))

Year — год

=ArrayFormula(IF(A2:A<>"";YEAR(A2:A);""))

QuarterOfYear — номер квартала

=ArrayFormula(IF(A2:A<>"";"Q" &INT((MONTH(A2:A) +2)/3);""))

MonthOfYear — номер месяца в году

=ArrayFormula(IF(A2:A<>"";MONTH(A2:A);""))

MonthDayNumber — номер дня в месяце

=ArrayFormula(IF(A2:A<>"";DAY(A2:A);""))

DateInt — дата в форме целого числа

=ArrayFormula(IF(A2:A<>"";A2:A;""))

YearMonthNumber — МесяцГод в форме 202301

=ArrayFormula(IF(A2:A<>"";VALUE( TEXT(A2:A;"yyyymm"));""))

MonthName — название месяца в формате Январь

=ArrayFormula(IF(A2:A<>"";VLOOKUP(D2:D;MonthName;2;FALSE);""))

MonthName — диапазон в котором соответствие номер месяца и названия в именительном падеже, находится на скрытом листе таблицы
MonthInCalendar — Месяц год в формате Янв 2023

=ArrayFormula(IF(A2:A<>"";TEXT(A2:A;"mmm yyy");""))

QuarterInCalendar — КварталГод в формате Q1 2023

=ArrayFormula(IF(A2:A<>"";C2:C&" "&B2:B;""))

DayInWeek — номер дня недели

=ArrayFormula(IF(A2:A<>"";WEEKDAY(A2:A;2);""))

DayOfWeekName — название дня недели

=ArrayFormula(IF(A2:A<>"";TEXT(A2:A;"dddd");""))

StartOfWeek — дата начала недели

=ArrayFormula(IF(A2:A<>"";A2:A-WEEKDAY(A2:A;3);""))

WeekEnding — дата окончания недели

=ArrayFormula(IF(A2:A<>"";N2:N+6;""))

Weeks — неделя от начала до конца

=ArrayFormula(IF(A2:A<>"";CONCAT(TEXT(N2:N;"YYYY.MM.DD")&"—";TEXT(O2:O;"YYYY.MM.DD"));""))

StartOfMonth — дата начала месяца

=ArrayFormula(IF(A2:A<>"";eomonth(A2:A;-1)+1;""))

StartOfMonth — дата окончания месяца

=ArrayFormula(IF(A2:A<>"";eomonth(A2:A;0);""))

WeekOfYear — номер недели в году

=ArrayFormula(IF(A2:A<>"";WEEKNUM(A2:A;2);""))

DayOfYear — номер дня от начала года

=ArrayFormula(IF(A2:A<>"";A2:A-DATE(YEAR(A2:A);1;1)+1;""))

WeekOfYear ISO 8601 — Год неделя по стандарту ISO 8601, применяется в Европе
Используется система 2. Первой неделей года считается та, в которую попадает первый четверг в году. Ее порядковым номером будет 1. В основе этой системы лежит международный стандарт представления дат и времени (ISO 8601).

=ARRAYFORMULA(
  IF(
    (MONTH(A2:A) = 1) * (WEEKNUM(A2:A; 21) > 50);
    TEXT(YEAR(A2:A) - 1; "0000") & "-" & TEXT(WEEKNUM(A2:A; 21); "00");
    TEXT(YEAR(A2:A); "0000") & "-" & TEXT(WEEKNUM(A2:A; 21); "00")
  )
)

Шаблон календаря для сквозной аналитики

Добавляем пользователя к разрешениям на папку

Скрипт на повершеле, для добавления пользователя к разрешениям на папку
Это может понадобится если нужно добавить права нового пользователя не убирая остальные права доступа. Например на папку «мои документы» определенного пользователя

$path = "e:\system volume information\"
$user = "DOMAIN\Administrator"
$Rights = "FullControl"

$InheritSettings = "Containerinherit, ObjectInherit"
$PropogationSettings = "None"
$RuleType = "Allow"
$acl = Get-Acl $path
$perm = $user, $Rights, $InheritSettings, $PropogationSettings, $RuleType
$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $perm
$acl.SetAccessRule($rule)
$acl | Set-Acl -Path $path

Правила передачи ACL: что такое «Containerinherit, ObjectInherit»
Права доступа: Read, Write, Modify и FullControl

Скачиваем видео с ютуба

Yt-dlp — утилита для скачивания роликов с ютуба, ниже команды которые я использую чаще всего.

Можно скачивать из других сервисов, например, рутуб.

Одиночное видео, в имени файла будет ай-ди ролика

yt-dlp -f "22/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" "https://www.youtube.com/watch?v=NdToAHst3BY"

Одиночное видео

yt-dlp -f "22/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" "https://www.youtube.com/watch?v=NdToAHst3BY" -o "%(title)s.%(ext)s"

Скачиваем список роликов, ссылки лежать в файле list.txt

yt-dlp -f "22/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" -a list.txt

Скачиваем плейлист

yt-dlp -f "22/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" "https://www.youtube.com/playlist?list=PLpZakfG8U02uo3HQ5dPe52yoUlcOOAssg"

Формат скачивания 720p

"22/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best"

Формат 22 обозначает 720p видео. Дальше если 720p формат недоступен, то будет загружено лучшее доступное видео формата mp4 с лучшим доступным аудио формата m4a. Если ни один из этих форматов недоступен, то будет загружено лучшее доступное видео формата mp4.

В ВК видео чтобы скачать 720p используем команду

yt-dlp -f "bestvideo[height<=720]+bestaudio/best[height<=720]"

На гитхабе yt-dlp, можно посмотреть опции, примеры использования yt-dlp, поддерживаемые сайты для скачивания

Для скачивания с геткурса, можно использовать плагин Stream Recorder

Как скачать защищенный pdf файл с гугл диска?

Дурим Шала, обновил код по скачиванию защищенного файла с гугл диска.
Код работает на сентябрь 2023 года, добавлена проверка политики безопасности, которая выводила ошибку

Файл скачивается в виде картинок упакованных в ПДФ.

Руководство по загрузке защищенного PDF-файла с Google Диска

  1. Откройте документ в Документах Google.
  2. Прокрутите документ до конца, чтобы были видны все страницы.
  3. Откройте «Инструменты разработчика» для этого на клавиатуре нажмите Ctrl+Shift+C
  4. Выберите вкладку «Консоль».
  5. Вставьте код и нажмите Enter.
  6. ПДФ скачается в виде картинок упакованных в ПДФ.
let trustedURL;
if (window.trustedTypes && trustedTypes.createPolicy) {
    const policy = trustedTypes.createPolicy('myPolicy', {
        createScriptURL: (input) => {
            return input;
        }
    });
    trustedURL = policy.createScriptURL('https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js');
} else {
    trustedURL = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js';
}

// Load the jsPDF library using the trusted URL.
let jspdf = document.createElement("script");
jspdf.onload = function () {
    // Generate a PDF from images with "blob:" sources.
    let pdf = new jsPDF();
    let elements = document.getElementsByTagName("img");
    for (let i = 0; i < elements.length; i++) {
        let img = elements[i];
        if (!/^blob:/.test(img.src)) {
            continue;
        }
        let canvasElement = document.createElement('canvas');
        let con = canvasElement.getContext("2d");
        canvasElement.width = img.width;
        canvasElement.height = img.height;
        con.drawImage(img, 0, 0, img.width, img.height);
        let imgData = canvasElement.toDataURL("image/jpeg", 1.0);
        pdf.addImage(imgData, 'JPEG', 0, 0);
        if (i !== elements.length - 1) {
            pdf.addPage();
        }
    }

    // Download the generated PDF.
    pdf.save("download.pdf");
};
jspdf.src = trustedURL;
document.body.appendChild(jspdf);

Если хотите до загрузки изменить имя download.pdf на свое. Измените имя в строке

pdf.save("download.pdf");

В измененном коде происходит проверка наличия поддержки Trusted Types в браузере.

Trusted Types — механизм безопасности веб-приложений.

В некоторых браузерах стоит запрет на вставку из буфера обмена в консоль, для активации вставки, наберите в консоли — allow pasting и нажмите энтер
  • Присутствует поддержка Trusted Types, создается политика Trusted Types под названием «myPolicy» определяющая как создавать безопасные URL. Затем создается доверенный URL для загрузки скрипта jspdf.min.js.
  • Отсутствует поддержка Trusted Types, используется стандартный URL для загрузки скрипта.

Вариант скрипта с фиксированным A4 в портретной ориентации (Portrait)

let trustedURL;
if (window.trustedTypes && trustedTypes.createPolicy) {
    const policy = trustedTypes.createPolicy('myPolicy', {
        createScriptURL: (input) => input
    });
    trustedURL = policy.createScriptURL('https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js');
} else {
    trustedURL = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js';
}

let jspdf = document.createElement("script");
jspdf.onload = function () {
    // PDF фиксированного размера A4
    let pdf = new jsPDF('p', 'mm', 'a4');

    let elements = document.getElementsByTagName("img");

    for (let i = 0; i < elements.length; i++) {
        let img = elements[i];
        if (!/^blob:/.test(img.src)) continue;

        // Рисуем изображение в canvas
        let canvasElement = document.createElement('canvas');
        let con = canvasElement.getContext("2d");
        canvasElement.width = img.naturalWidth;
        canvasElement.height = img.naturalHeight;
        con.drawImage(img, 0, 0);

        // Получение JPEG из canvas
        let imgData = canvasElement.toDataURL("image/jpeg", 1.0);

        // Вставляем картинку на лист A4 по всей странице
        pdf.addImage(imgData, 'JPEG', 0, 0, 210, 297);

        if (i !== elements.length - 1) {
            pdf.addPage();
        }
    }

    pdf.save("download.pdf");
};

jspdf.src = trustedURL;
document.body.appendChild(jspdf);

Вариант скрипта с фиксированным A4 в альбомной ориентации (Landscape)

let trustedURL;
if (window.trustedTypes && trustedTypes.createPolicy) {
    const policy = trustedTypes.createPolicy('myPolicy', {
        createScriptURL: (input) => input
    });
    trustedURL = policy.createScriptURL('https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js');
} else {
    trustedURL = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js';
}

let jspdf = document.createElement("script");
jspdf.onload = function () {

    // PDF A4 landscape: 297mm × 210mm
    let pdf = new jsPDF('l', 'mm', 'a4');

    let elements = document.getElementsByTagName("img");

    for (let i = 0; i < elements.length; i++) {
        let img = elements[i];
        if (!/^blob:/.test(img.src)) continue;

        // Создаем canvas по натуральным размерам изображения
        let canvasElement = document.createElement('canvas');
        let con = canvasElement.getContext("2d");
        canvasElement.width = img.naturalWidth;
        canvasElement.height = img.naturalHeight;
        con.drawImage(img, 0, 0);

        // Конвертируем в JPEG
        let imgData = canvasElement.toDataURL("image/jpeg", 1.0);

        // Вставляем изображение на всю страницу A4 landscape
        pdf.addImage(imgData, 'JPEG', 0, 0, 297, 210);

        if (i !== elements.length - 1) {
            pdf.addPage();
        }
    }

    pdf.save("download.pdf");
};

jspdf.src = trustedURL;
document.body.appendChild(jspdf);

Пакетное скачивание защищенных пдф файлов

gdrive_pdf_saver — проект на гитхабе, нужен питон.

Генерируем таблицу учета времени

Студия Crauch выложила внутренние документы которые используют в проектах.

Таблица учета времени. В шаблоне коммерческих предложений подробнее объясняются внутренности таблицы

Сказано: «Это таблица учета времени проекта в студии. Часы в ней подбиваем каждый день, чтобы клиент мог видеть сколько часов и денег потрачено.»

Предположим что мы заказчики и смотрим на эту таблицу, видим следующие проблемы:

  • Цветовое кодирование. Сейчас используются три специалиста и четыре цвета, четвертый цвет — серый, для отделения этапов работ. Что будет с таблицей если нужно добавить дополнительных специалистов?
  • Легенда разделена с таблицей. Если прокрутить таблицу право, на окончание месяца, легенды видно не будет.
  • Ручное заполнение таблицы. Возможны ошибки заполнения связанные с человеческим фактором.
  • Нет описания работ специалиста. Иногда требуется ответить на вопрос: что делал мидл дизайнер 7 октября с дизайном главной страницы.

Сделаем свою версию таблицу

Сгенерированная таблица с данными на текущий месяц в которой прописан: дата, этап, исполнитель, затраченные часы, стоимость работы, проводимые работы
Создаем лист справочника, в нем несколько таблиц: «Специалист — ставка специалиста», «Этапы работ», «Возможное время на работу», «глаголы для описания подробной работы»

Генерируем данные

Дата в текущем месяце, нам не важно какая будет дата, главное в этом месяце

=EOMONTH(TODAY();-1)+1+RANDBETWEEN(0;EOMONTH(TODAY();0)-EOMONTH(TODAY();-1)-1)

Этап

=INDEX('справочник'!$E$2:$E$8;RANDBETWEEN(1;7);1)

Исполнитель

=INDEX('справочник'!$A$2:$E$5;RANDBETWEEN(1;4);1)

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

=INDEX('справочник'!$H$2:$H$25;RANDBETWEEN(1;24);1)*VLOOKUP(C2;'справочник'!A:C;3;False)

Стоимость работ

=VLOOKUP(C2;'справочник'!A:B;2;FALSE)*24*D2

Что сделал

=JOIN(" ";C2;INDEX('справочник'!$L$2:$L$5;RANDBETWEEN(1;4);1);"в этапе";B2)
Протягиваем все ячейки и получаем таблицу, в которой данные идут вперемешку

На новом листе сортируем данные

=SORT('данные_авто'!A2:F;1;True)
И получаем таблицу, данные в ней отличаются от моих, так как при каждом обновлении таблицы, происходит перегенерация

Остается сделать сводные таблицы, как в примере

Полная стоимость в этом месяце, сколько часов было затрачено, средняя ставка в час
Разбивка по затратам на каждый этап
Разбивка по исполнителям

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

Ссылка на получившуюся таблицу

Запуск удаленного рабочего стола (RDP) в Windows 11 Home

К Windows 11 Home нельзя подключиться по RDP, эта функция заблокирована.

Включаем RDP в Windows Home

Работает для версий Windows 10 и 11.

Для разблокировки:

Скачиваем RDP Wrapper 1.6.2 и распаковываем в директорию на  диске.
Скачиваем обновление rdpwrap.ini в эту же директорию.
Открываем командную строчку CMD как администратор в этой директории

Запускаем

RDPWinst -u -k

Запускаем

RDPWinst -i

Не используем install.bat

Для проверки запускаем RDPConf, если статус лицензии — лицензирован, все работает

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

Если RDP Wrapper — проблема Not listening [not supported] проявится опять, нужно повторить все шаги

Включение входа не администраторов

Изучаем статью как добавить не администраторов в RDP в Windows 7

Качаем или создаем файл реестра

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Builtin\Aliases\0000022B]
"C"=hex:2b,02,00,00,00,00,00,00,b0,00,00,00,02,00,01,00,b0,00,00,00,28,00,00,\
00,00,00,00,00,d8,00,00,00,7a,00,00,00,00,00,00,00,54,01,00,00,00,00,00,00,\
00,00,00,00,01,00,14,80,90,00,00,00,a0,00,00,00,14,00,00,00,44,00,00,00,02,\
00,30,00,02,00,00,00,02,c0,14,00,13,00,05,01,01,01,00,00,00,00,00,01,00,00,\
00,00,02,c0,14,00,ff,ff,1f,00,01,01,00,00,00,00,00,05,07,00,00,00,02,00,4c,\
00,03,00,00,00,00,00,14,00,0c,00,02,00,01,01,00,00,00,00,00,01,00,00,00,00,\
00,00,18,00,1f,00,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,20,02,00,00,00,\
00,18,00,1f,00,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,24,02,00,00,01,02,\
00,00,00,00,00,05,20,00,00,00,20,02,00,00,01,02,00,00,00,00,00,05,20,00,00,\
00,20,02,00,00,52,00,65,00,6d,00,6f,00,74,00,65,00,20,00,44,00,65,00,73,00,\
6b,00,74,00,6f,00,70,00,20,00,55,00,73,00,65,00,72,00,73,00,4d,00,65,00,6d,\
00,62,00,65,00,72,00,73,00,20,00,69,00,6e,00,20,00,74,00,68,00,69,00,73,00,\
20,00,67,00,72,00,6f,00,75,00,70,00,20,00,61,00,72,00,65,00,20,00,67,00,72,\
00,61,00,6e,00,74,00,65,00,64,00,20,00,74,00,68,00,65,00,20,00,72,00,69,00,\
67,00,68,00,74,00,20,00,74,00,6f,00,20,00,6c,00,6f,00,67,00,6f,00,6e,00,20,\
00,72,00,65,00,6d,00,6f,00,74,00,65,00,6c,00,79,00,00,00

[HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Builtin\Aliases\Names\Remote Desktop Users]
@=hex(22b):

Скачиваем psexec

Запускаем PsExec.exe с правами администратора в командной строке

PsExec.exe -s -i regedit.exe

В редакторе реестра импортируем файл реестра

Проверить, что появилась группа «Пользователи удаленного рабочего стола», для этого качаем Local User and Group Management

Группа «Пользователи удаленного рабочего стола» находится во вкладке «Группы»
Добавляем нашего пользователя в группу «Пользователи удаленного рабочего стола»

Проверяем, все должно работать.

Мне помогли в телеграм чате помощи по RDP Wrapper

«Яндекс Дзен: Промостраницы» отчет для клиента

Вариант решения тестового задания от АКМ Стратегия. Можно попробовать свои силы и написать решение задания Ольге Князевой

Подготовили отчет для клиента, как вы считаете, что нужно поправить и как оформить это лучше?

Отчет сделал таргетолог. В реальности отчет нужно прокручивать, для читаемости скриншотов разделен на два.

В отчете содержатся фактические ошибки, которые исправим:

  • цифры в виде текста,
  • рассчитываемые столбцы посчитаны на калькуляторе, а не формулами.
  • часть данных не учтено, например, не просуммированы конверсии.

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

Для чего этот отчет нужен?

Этот вопрос задаем клиенту, чтобы сделать отчет.
На основании отчета клиент понимает:

  • По какой цене лид с каждой рекламной статьи,
  • Какая статья самая эффективная, с точки зрения цены лида,
  • Какую рекламную статью можно остановить.

Для отчета это:

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

Построение план-факта нарастающим итогом в гугл таблицах

Есть таблица у которой в каждой строке транзации, построим план-факт нарастающим итогом.

Исходная таблица: Дата совершения транзакции, вид транзакции, сумма транзакции

Добавим столбец который будет считать выручку, если возврат умножаем на -1

=ArrayFormula(IF(B2:B="возврат";C2:C*-1;C2:C))
Получаем столбец выручка, можем производить операции сложения.

На какую дату строить отчет, в нашем случае это вчерашний вечер

=TODAY()-1

Первый день месяца

=EOMONTH(B2;-1)+1

Последний день месяца

=EOMONTH(B2;0)

Количество дней в месяце

=DATEDIF(B3;B4+1;"D")

План в день = план в месяц / количество дней в месяце

Получившиеся ячейки, данные в оранжевых ячейках можно править
При помощи формул сложения и дат строим таблицу план-факт нарастающим итогом до текущей даты

Формула следующего дня

=IF(AND(F31+1<=$B$2;F31<>"");F31+1;"")

Формула проверяет выполнение двух условий с помощью функции AND():

  • Увеличенное на 1 значение ячейки F31 не должно превышать или быть равным значению, указанному в ячейке B2. Эта ячейка содержит дату отчета.
  • Сама ячейка F31 не должна быть пустой.
    Если оба эти условия выполняются, то формула возвращает значение ячейки F31, увеличенное на 1. Если же одно из условий не выполняется, то формула возвращает пустую строку.
Вычисляем план, факт и процент выполнения плана на сегодня
Строим график сравнения плана и факта нарастающим итогом

Данные в таблице сгенерированы и обновляются при изменении.

При генерации использован следующий алгоритм:
Даты случайным образом генерируются от текущей даты три месяца назад

=RANDBETWEEN(EOMONTH(TODAY();-3);TODAY())

Вид транзакции формируется случайно: оплата или возврат
Сумма возврата между 100—500 ₽
Сумма оплаты между 100—3000 ₽

Итоговая таблица план-факта выручки

Ранее Ctrl + ↓