Производственный календарь, т.е. список дат, где соответствующим образом помечены все официальные рабочие и выходные дни — совершенно необходимая штука для любого пользователя Microsoft Excel. На практике без него не обойтись:
- в бухгалтерских расчетах (зарплата, стаж, отпуска…)
- в логистике — для корректного определения сроков доставки с учётом выходных и праздников (помните классическое «давай уже после праздников?»)
- в управлении проектами — для правильной оценки сроков с учётом, опять же, рабочих-нерабочих дней
- при любом использовании функций типа РАБДЕНЬ (WORKDAY) или ЧИСТРАБДНИ (NETWORKDAYS), т.к. они требуют в качестве аргумента список праздников
- при использовании функций Time Intelligence (типа TOTALYTD, TOTALMTD, SAMEPERIODLASTYEAR и т.д.) в Power Pivot и Power BI
- … и т.д. и т.п. — примеров масса.
Тем, кто работает в корпоративных ERP-системах типа 1С или SAP — проще, в них производственный календарь встроен. Но что делать пользователям Excel?
Можно, конечно, вести такой календарь вручную. Но тогда придется как минимум раз в год (а то и чаще, как в «весёлом» 2020 году) его актуализировать, аккуратно внося туда все выходные, переносы и нерабочие дни, придуманные нашим правительством. А потом повторять эту процедуру каждый следующий год. Скукота.
А как насчёт чуть напрячься и сделать «вечный» производственный календарь в Excel? Такой, чтобы сам обновлялся, брал данные из интернета и формировал всегда актуальный список нерабочих дней для последующего использования в любых расчетах? Заманчиво?
Сделать такое, на самом деле, совсем не сложно.
Источник данных
Главный вопрос — а где брать данные? В поисках подходящего источника я перебрал несколько вариантов:
- Оригинальные указы публикуются на сайте правительства в формате PDF (вот, один из них, например) и отпадают сразу — полезную информацию из них не вытащить.
- Заманчивым вариантом, на первый взгляд, казался «Портал открытых данных РФ», где есть соответствующий набор данных, но, при ближайшем изучении всё оказалось печально. Для импорта в Excel сайт жутко неудобен, техподдержка не отвечает (самоизолировались?), да и сами данные там давно устарели — производственный календарь на 2020 год обновлялся последний раз в ноябре 2019 (позорище!) и, само-собой, не содержит наших «коронавирусных» и «голосовательных» выходных 2020 года, например.
Разочаровавшись в официальных источниках, я стал рыть неофициальные. Их в интернете множество, но большинство из них, опять же, совершенно неприспособлены для импорта в Excel и выдают производственный календарь в виде красивых картинок. Но нам-то с вами не на стенку его вешать, правильно?
И вот в процессе поисков случайно обнаружилось прекрасное — сайт http://xmlcalendar.ru/
Без лишних «рюшечек», простой, легкий и быстрый сайт, заточенный под одну задачу — отдавать всем желающим производственный календарь за нужный год в XML-формате. Отлично!
Если, вдруг, вы не в курсе, то XML — это текстовый формат с разметкой содержимого специальными <тегами>. Легкий, удобный и читаемый большинством современных программ, включая Excel.
Я, на всякий случай, связался с авторами сайта и они подтвердили, что сайт существует уже 7 лет, данные на нем постоянно актуализируются (у них для этого даже ветка на github есть) и закрывать его они не собираются. И совершенно не против, чтобы мы с вами с него грузили данные для любых наших проектов и расчётов в Excel. Бесплатно. Как же приятно, что есть еще такие люди! Респектище!
Осталось загрузить эти данные в Excel с помощью надстройки Power Query (для версий Excel 2010-2013 её можно бесплатно скачать с сайта Microsoft, а в версиях Excel 2016 и новее — она уже встроена по умолчанию).
Логика действий будет такая:
- Делаем запрос для загрузки данных с сайта за один любой год
- Превращаем наш запрос в функцию
- Применяем эту функцию к списку всех имеющихся лет, начиная с 2013 и до текущего года — и получаем «вечный» производственный календарь с автоматическим обновлением. Вуаля!
Шаг 1. Импортируем календарь за один год
Сначала загрузим производственный календарь за один любой год, например, за 2020. Для этого в Excel идём на вкладку Данные (или Power Query, если вы установили её как отдельную надстройку) и выбираем Из интернета (From Web). В открывшееся окно вставляем ссылку на соответствующий год, скопированную с сайта:
После нажатия на ОК появляется окно предварительного просмотра, в котором нужно нажать кнопку Преобразовать данные (Transform data) или Изменить данные (Edit data) и мы попадем в окно редактора запросов Power Query, где и продолжим работу с данными:
Сразу же можно смело удалить в правой панели Параметры запроса (Query settings) шаг Измененный тип (Changed Type) — он нам не нужен.
Таблица в столбце holidays содержит коды и описания нерабочих дней — увидеть её содержимое можно, дважды «провалившись» в неё щелчком мыши по зелёному слову Table:
Для возврата назад придется удалить в правой панели все появившиеся шаги обратно до Источника (Source).
Вторая таблица, куда можно зайти аналогичным образом, содержит как раз то, что нам нужно — даты всех нерабочих дней:
Останется эту табличку обработать, а именно:
1. Отфильтровать только даты праздников (т.е. единички) по второму столбцу Attribute:t
2. Удалить все столбцы, кроме первого — щелчком правой кнопкой мыши по заголовку первого столбца и выбором команды Удалить другие столбцы (Remove Other Columns):
3. Разделить первый столбец по точке отдельно на месяц и день с помощью команды Разделить столбец — По разделителю на вкладке Преобразование (Transform — Split column — By delimiter):
4. И, наконец, создать вычисляемый столбец с нормальными датами. Для этого на вкладке Добавление столбца жмём на кнопку Настраиваемый столбец (Add Column — Custom Column) и вводим в появившееся окно следующую формулу:
=#date(2020, [#»Attribute:d.1″], [#»Attribute:d.2″])
Здесь у оператора #date три аргумента: год, месяц и день, соответственно. После нажатия на ОК получаем требуемый столбец с нормальными датами выходных, а остальные столбцы удаляем как в п.2
Шаг 2. Превращаем запрос в функцию
Следующая наша задача — преобразовать созданный на 2020 год запрос в универсальную функцию для любого года (номер года будет её аргументом). Для этого делаем следующее:
1. Разворачиваем (если ещё не развернута) панель Запросы (Queries) слева в окне Power Query:
2. После преобразования запроса в функцию возможность видеть шаги, из которых состоит запрос и легко их редактировать, к сожалению, пропадает. Поэтому имеет смысл сделать копию нашего запроса и резвиться уже с ней, а оригинал оставить про запас. Для этого щелкаем правой кнопкой мыши в левой панели по нашему запросу calendar и выбираем команду Дублировать (Duplicate).
Щелкнув еще раз правой по получившейся копии calendar(2) выберем команду Переименовать (Rename) и введём новое имя — пусть будет, например, fxYear:
3. Открываем исходный код запроса на внутреннем языке Power Query (он лаконично назвается «М») с помощью команды Расширенный редактор на вкладке Просмотр (View — Advanced Editor) и вносим туда небольшие правки для превращения нашего запроса в функцию на любой год.
Было:
Стало:
Если интересны подробности, то здесь:
- (year as number)=> — объявляем, что в нашей функции будет один числовой аргумент — переменная year
- Подклеиваем переменную year в веб-ссылку на шаге Источник. Поскольку Power Query не позволяет склеивать числа и текст, то на лету преобразовываем номер года в текст с помощью функции Number.ToText
- Подставляем переменную year вместо 2020 года на предпоследнем шаге #»Добавлен пользовательский объект«, где мы формировали дату из фрагментов.
После нажатия на Готово наш запрос превращается в функцию:
Шаг 3. Импортируем календари за все года
Осталась самая малость — сделать последний главный запрос, который будет закачивать данные за все имеющиеся года и складывать все полученные даты праздников в одну таблицу. Для этого:
1. Щёлкаем в левой панели запросов в серое пустое место правой кнопкой мыши и выбираем последовательно Новый запрос — Другие источники — Пустой запрос (New Query — From other sources — Blank query):
2. Нам нужно сформировать список всех лет, для которых мы будем запрашивать календари, т.е. 2013, 2014 … 2020. Для этого в строке формул появившегося пустого запроса вводим команду:
Конструкция:
={ЧислоА..ЧислоБ}
… в Power Query формирует список целых чисел от А до Б. Например, выражение
={1..5}
…выдало бы список 1,2,3,4,5.
Ну, а чтобы не привязываться жёстко к 2020 году, мы используем функцию DateTime.LocalNow() — аналог экселевской функции СЕГОДНЯ (TODAY) в Power Query — и извлекаем из неё, в свою очередь, текущий год функцией Date.Year.
3. Полученный набор лет хоть и выглядит вполне адекватно, но для Power Query представляет собой не таблицу, а особый объект — список (List). Но преобразовать его в таблицу — не проблема: достаточно нажать кнопку В таблицу (To Table) в левом верхнем углу:
4. Финишная прямая! Применяем созданную нами ранее функцию fxYear к полученному списку лет. Для этого на вкладке Добавление столбца жмём кнопку Вызвать настраиваемую функцию (Add Column — Invoke Custom Function) и задаём её единственный аргумент — колонку Column1 с годами:
После нажатия на ОК наша функция fxYear по очереди отработает импорт для каждого года и мы получим столбец, где в каждой ячейке будет содержаться таблица с датами нерабочих дней (содержимое таблицы хорошо видно, если щёлкнуть мышью в фон ячейки рядом со словом Table):
Останется развернуть содержимое вложенных таблиц, щёлкнув по значку с двойными стрелками в шапке столбца Даты (галочку Использовать исходное имя столбца как префикс при этом можно снять):
… и после нажатия на ОК мы получим то, что хотели — список всех праздников с 2013 и до текущего года:
Первый, ненужный уже столбец, можно удалить, а для второго задать тип данных Дата (Date) в выпадающем списке в шапке столбца:
Сам запрос можно переименовать как-нибудь более осмысленно, чем Запрос1 и выгрузить затем результаты на лист в виде динамической «умной» таблицы с помощью команды Закрыть и загрузить на вкладке Главная (Home — Close & Load):
Обновлять созданный календарь в будущем можно щелчком правой кнопки мыши по таблице или запросу в правой панели через команду Обновить. Или же использовать кнопку Обновить все на вкладке Данные (Date — Refresh All) или сочетание клавиш Ctrl+Alt+F5.
Вот и всё.
Теперь вам больше никогда не нужно тратить время и мыслетопливо на поиски и актуализацию списка праздничных дней — теперь у вас есть «вечный» производственный календарь. Во всяком случае, до тех пор, пока авторы сайта http://xmlcalendar.ru/ поддерживают своё детище, что, я надеюсь, будет ещё очень и очень долго (спасибо им еще раз!).
Ссылки по теме
- Импорт курса биткойна в Excel из интернета через Power Query
- Поиск ближайшего рабочего дня функцией РАБДЕНЬ (WORKDAY)
- Поиск пересечения интервалов дат
04.01.2023
Другие года: 2023, 2022, 2021, 2020, 2019, 2018, 2017, 2016.
Согласно статье 112 Трудового кодекса Российской Федерации (в ред. ФЗ № 35-ФЗ от 23 апреля 2012 года) нерабочими праздничными днями в Российской Федерации являются:
Праздники в 2023 году:
✅ 31 декабря 2022 года — выходной день.
✅ 1, 2, 3, 4, 5, 6 и 8 января — Новый год (новогодние каникулы);
✅ 7 января — Рождество Христово;
✅ 23 февраля — День защитника Отечества;
✅ 8 марта — Международный женский день;
✅ 1 мая — Праздник Весны и Труда;
✅ 9 мая — День Победы;
✅ 12 июня — День России;
✅ 4 ноября — День народного единства.
Перенос выходных дней ежегодно осуществляется Правительством России в целях рационального планирования рабочего времени в организациях и учета интересов различных категорий работников по созданию условий для полноценного отдыха.
Согласно Постановлению Правительства РФ от 29.08.2022 № 1505 «О переносе выходных дней в 2023 году» (ссылка) разработан перенос выходных дней в 2023 году с праздничных дней:
• с 01.01 (воскресенье) на 24.02 (пятница);
• с 08.01 (воскресенье) на 08.09 (понедельник);
Предпраздничные дни в 2023 году:
• вторник 22 февраля, вторник 7 марта, пятница 3 ноября.
Итого 3 предпраздничных дня в 2023 году.
Скачать Производственный календарь 2023 в excel (xls, таблица «Норма времени» на 2 странице)
Согласно статье 112 Трудового кодекса РФ при совпадении выходного и нерабочего праздничного дней выходной день переносится на следующий после праздничного рабочий день. Исключение составляют выходные дни, совпадающие с нерабочими праздничными днями января. Изменениями, внесенными в ст. 112 ТК РФ Федеральным законом от 23.04.2012 № 35-ФЗ, предусматривается, что Правительство Российской Федерации вправе переносить два выходных дня из числа выходных дней, совпадающих с нерабочими январскими праздничными днями, на другие дни в очередном календарном году.
Норма рабочего времени в 2023 году
Период | Д кален дарных |
Д рабочих | Д выход, празд. |
Д пред- празд. |
Часы 40- часовая |
Часы 36- часовая |
Часы 24- часовая |
Январь | 31 | 17 | 14 | 0 | 136,0 | 122,4 | 81,6 |
Февраль | 28 | 18 | 10 | 1 | 143,0 | 128,6 | 85,4 |
Март | 31 | 22 | 9 | 1 | 175,0 | 157,4 | 104,6 |
1 квартал | 90 | 57 | 33 | 2 | 454,0 | 408,4 | 271,6 |
Апрель | 30 | 20 | 10 | 0 | 160,0 | 144,0 | 96,0 |
Май | 31 | 20 | 11 | 0 | 160,0 | 144,0 | 96,0 |
Июнь | 30 | 21 | 9 | 0 | 168,0 | 151,2 | 100,8 |
2 квартал | 91 | 61 | 30 | 0 | 488,0 | 439,2 | 292,8 |
1 полугодие | 181 | 118 | 63 | 2 | 942,0 | 847,6 | 564,4 |
Июль | 31 | 21 | 10 | 0 | 168,0 | 151,2 | 100,8 |
Август | 31 | 23 | 8 | 0 | 184,0 | 165,6 | 110,4 |
Сентябрь | 30 | 21 | 9 | 0 | 168,0 | 151,2 | 100,8 |
3 квартал | 92 | 65 | 27 | 0 | 520,0 | 468,0 | 312,0 |
Октябрь | 31 | 22 | 9 | 0 | 176,0 | 158,4 | 105,6 |
Ноябрь | 30 | 21 | 9 | 1 | 167,0 | 150,2 | 99,8 |
Декабрь | 31 | 21 | 10 | 0 | 168,0 | 151,2 | 100,8 |
4 квартал | 92 | 64 | 28 | 1 | 511,0 | 459,8 | 306,2 |
2 полугодие | 184 | 129 | 55 | 1 | 1 031,0 | 927,8 | 618,2 |
Год | 365 | 247 | 118 | 3 | 1 973,0 | 1 775,4 | 1 182,6 |
Согласно статье 91 ТК РФ (в ред. Федерального закона от 22 июля 2008 г. N 157-ФЗ) Порядок исчисления нормы рабочего времени на определенные календарные периоды (месяц, квартал, год) в зависимости от установленной продолжительности рабочего времени в неделю определяется федеральным органом исполнительной власти, осуществляющим функции по выработке государственной политики и нормативно-правовому регулированию в сфере труда.» (Собрание законодательства Российской Федерации, 2008, N 30 (ч. I), ст. 3613).
В настоящее время действует Порядок исчисления нормы рабочего времени на определенные календарные периоды времени (месяц, квартал, год) в зависимости от установленной продолжительности рабочего времени в неделю, утвержденный приказом Минздравсоцразвития России от 13 августа 2009 г. N 588н (Бюллетень трудового и социального законодательства РФ, 2009, N 10).
Согласно установленному Порядку исчисления нормы рабочего времени данная норма исчисляется по расчетному графику пятидневной рабочей недели с двумя выходными днями в субботу и воскресенье, исходя из продолжительности ежедневной работы (смены), например, при 40-часовой рабочей неделе — 8 часов, при продолжительности рабочей недели 36 часов она составит 7,2 часа; при 24-часовой рабочей неделе — 4,8 часа. Продолжительность рабочего дня или смены, непосредственно предшествующих нерабочему праздничному дню, уменьшается на один час.
Рассчитанная в приведенном порядке норма рабочего времени распространяется на все режимы труда и отдыха.
Итого
Всего в 2023 году 365 дней (не високосный год) при пятидневной рабочей неделе с двумя выходными днями; 247 рабочих дня, в том числе 3 предпраздничных дня (сокращенных на один час рабочих дней) и 118 выходных и праздничных дней.
Норма рабочего времени в 2023 году составляет:
при 40-часовой рабочей неделе — 1 973,0 часа = 8,0 час. x 247 дней — 3 часа;
при 36-часовой рабочей неделе — 1 775,4 часа = 7,2 час. x 247 дней — 3 часа;
при 24-часовой рабочей неделе — 1 182,6 часа = 4,8 час. x 247 дней — 3 часа.
Теперь разберём, как загрузить в Excel производственный календарь для последующего использования. В статье показан один из вариантов, далеко не единственный.
В качестве источника данных воспользуемся набором на Портале открытых данных РФ (
https://data.gov.ru/opendata/7708660670-proizvcalendar).
Раскроем паспорт набора:
Набор представляет собой производственный календарь c 1999 до 2025 года. Звездочкой (*) отмечены предпраздничные (сокращенные) дни. Плюсом (+) отмечены перенесенные выходные дни.
Для загрузки в Excel скопируем ссылку на набор (https://data.gov.ru/opendata/7708660670-proizvcalendar/data-20191112T1252-structure-20191112T1247.csv):
Запустим Excel. Воспользуемся коннектором для получения данных с Web-страницы (вкладка “Данные” — “Создать запрос” — “Из других запросов” — “Из Интернета”):
В открывшемся диалоге вставим скопированную ранее ссылку на набор:
Предварительный просмотр данных показывает, что в таком виде данными пользоваться будет крайне сложно. Обработаем данные в Power Query.
Загруженный набор данных в каждой строке хранит описание для одного года — сначала на каждый месяц — через запятую список дней (выходных, сокращённых и дополнительных выходных), затем несколько статистических столбцов.
Удалим статистические столбцы. Они нам не пригодятся. Наша цель — таблица, где на каждую дату будет признак — рабочий, выходной или сокращённый рабочий (последний вариант — опциональный, такие дни можно тоже интерпретировать как рабочие, в зависимости от задачи):
Итого, у нас осталось 13 колонок — колонка с годом и с каждый месяцем. Развернём колонки с месяцами в плоский список. Для этого воспользуемся командой “Отменить свёртывание столбцов”:
Команда “Отменить свёртывание столбцов” создаёт пары для каждого сочетания названия столбца и ячейки в этом столбце и превращает их в столбцы:
Далее разделим столбец с днями на отдельные столбцы с помощью команды ”Разделить столбец” — “По разделителю”:
В качестве разделителя укажем запятую, разделим по каждому вхождения разделителя:
Получим 16 столбцов с числами — столько, сколько их значится в максимуме в некоторых месяцах. Там, где значений в ячейке было менее 16 — лишние столбцы остались со значением null. Произведём с числами ту же операцию, которую произвели с месяцами — развернём в плоский список с помощью команды “Отменить свёртывание столбцов”:
И получим таблицу, где каждая строка — характеристики одной даты. Столбец “Атрибут.1” появился как порядковый номер конкретного числа в ячейке, он не пригодится. Удалим его:
Теперь мы можем обработать звёздочки и плюсики, присвоив каждой строке (= каждой дате) некоторый признак. Чтобы далее использовать вычисление, определяющее вхождение символов * или + в строку — нам необходимо преобразовать столбец в текст:
Далее добавляем условный столбец, который будет присваивать признак каждому дню в зависимости от вхождения * и +:
Пропишем условие определения признака следующим образом: если в значении дня (столбец “Значение”) присутствует символ *, то считаем такой день сокращённым рабочим, иначе — выходным. Мы могли бы добавить ещё одно условие для вхождения символа +, но такие дни тоже являются выходными, хоть и добавленными. Можно выделить это тип дней отдельно, если этого требует задача. Мы выделять не будем:
Получаем вот такой столбец:
Теперь можно избавить из дополнительных символов у числа (* и +), чтобы перейти к дальнейшим шагам обработки. Для удаления символов воспользуемся командой “Замена значений”:
Заменим звёздочку на “ничего”. Оставим поле с итоговым значением пустым. Это будет равносильно тому, чтобы удалить выбранные подстроки (в данном случае — звёздочки):
Проделаем аналогичную операцию для удаления плюсиков. Теперь у нас есть три столбца — части даты. Соберём их в дату с помощью вычисляемого столбца:
Сбор даты из элементов можно произвести несколько способами. Рассмотрим один из вариантов — соберём все элементы даты в текстовую строку и преобразуем в дату. Date.From — преобразовывает текст в дату. Text.Combine — объединяет несколько текстовых строк в одну. Text.From — преобразуем нетекстовое значение к текст. Точки между элементами даты добавим для разделения (можно воспользоваться другим символом, например, тире):
Date.From(
Text.Combine(
{
[Значение],
«.»,
[Атрибут],
«.»,
Text.From([#»Год/Месяц»])
}
)
)
В результате получим столбец с датой — Date. Теперь можем удалить составные столбцы — они свою роль сыграли:
Осталось скорректировать типы данных. Поставить, что столбец Date — это данные типа Дата, Day type — Текст:
Результат:
Итоговый код обработки данных:
let
Источник = Csv.Document(Web.Contents(«https://data.gov.ru/opendata/7708660670-proizvcalendar/data-20191112T1252-structure-20191112T1247.csv»),[Delimiter=»,», Columns=18, Encoding=65001, QuoteStyle=QuoteStyle.None]),
#»Повышенные заголовки» = Table.PromoteHeaders(Источник, [PromoteAllScalars=true]),
#»Измененный тип» = Table.TransformColumnTypes(#»Повышенные заголовки»,{{«Год/Месяц», Int64.Type}, {«Январь», type text}, {«Февраль», type text}, {«Март», type text}, {«Апрель», type text}, {«Май», type text}, {«Июнь», type text}, {«Июль», type text}, {«Август», type text}, {«Сентябрь», type text}, {«Октябрь», type text}, {«Ноябрь», type text}, {«Декабрь», type text}, {«Всего рабочих дней», Int64.Type}, {«Всего праздничных и выходных дней», Int64.Type}, {«Количество рабочих часов при 40-часовой рабочей неделе», Int64.Type}, {«Количество рабочих часов при 36-часовой рабочей неделе», type text}, {«Количество рабочих часов при 24-часовой рабочей неделе», type text}}),
#»Удаленные столбцы» = Table.RemoveColumns(#»Измененный тип»,{«Всего рабочих дней», «Всего праздничных и выходных дней», «Количество рабочих часов при 40-часовой рабочей неделе», «Количество рабочих часов при 36-часовой рабочей неделе», «Количество рабочих часов при 24-часовой рабочей неделе»}),
#»Несвернутые столбцы» = Table.UnpivotOtherColumns(#»Удаленные столбцы», {«Год/Месяц»}, «Атрибут», «Значение»),
#»Разделить столбец по разделителю» = Table.SplitColumn(#»Несвернутые столбцы», «Значение», Splitter.SplitTextByDelimiter(«,», QuoteStyle.Csv), {«Значение.1», «Значение.2», «Значение.3», «Значение.4», «Значение.5», «Значение.6», «Значение.7», «Значение.8», «Значение.9», «Значение.10», «Значение.11», «Значение.12», «Значение.13», «Значение.14», «Значение.15», «Значение.16»}),
#»Измененный тип1″ = Table.TransformColumnTypes(#»Разделить столбец по разделителю»,{{«Значение.1», type text}, {«Значение.2», type text}, {«Значение.3», type text}, {«Значение.4», type text}, {«Значение.5», type text}, {«Значение.6», type text}, {«Значение.7», type text}, {«Значение.8», type text}, {«Значение.9», type text}, {«Значение.10», type text}, {«Значение.11», type text}, {«Значение.12», type text}, {«Значение.13», Int64.Type}, {«Значение.14», Int64.Type}, {«Значение.15», Int64.Type}, {«Значение.16», Int64.Type}}),
#»Несвернутые столбцы1″ = Table.UnpivotOtherColumns(#»Измененный тип1″, {«Год/Месяц», «Атрибут»}, «Атрибут.1», «Значение»),
#»Удаленные столбцы1″ = Table.RemoveColumns(#»Несвернутые столбцы1″,{«Атрибут.1»}),
#»Измененный тип2″ = Table.TransformColumnTypes(#»Удаленные столбцы1″,{{«Значение», type text}}),
#»Условный столбец добавлен» = Table.AddColumn(#»Измененный тип2″, «Date type», each if Text.Contains([Значение], «*») then «Сокращённый рабочий» else «Выходной»),
#»Замененное значение» = Table.ReplaceValue(#»Условный столбец добавлен»,»*»,»»,Replacer.ReplaceText,{«Значение»}),
#»Замененное значение1″ = Table.ReplaceValue(#»Замененное значение»,»+»,»»,Replacer.ReplaceText,{«Значение»}),
#»Добавлен пользовательский объект» = Table.AddColumn(#»Замененное значение1″, «Date», each Date.From(
Text.Combine(
{
[Значение],
«.»,
[Атрибут],
«.»,
Text.From([#»Год/Месяц»])
}
)
)),
#»Удаленные столбцы2″ = Table.RemoveColumns(#»Добавлен пользовательский объект»,{«Год/Месяц», «Атрибут», «Значение»}),
#»Измененный тип3″ = Table.TransformColumnTypes(#»Удаленные столбцы2″,{{«Date type», type text}})
in
#»Измененный тип3″
*****
Получили почти то, что хотели, за исключением одного “но” — в итоговой таблице нет рабочих дней. Для решения некоторых задач полученного результата вполне достаточно. Кроме того, обработку дней мы можем далее заложить логикой (а-ля “Всё, что не в таблице — рабочие дни”). Но — закончим задачу для полноценного календаря, где тип присвоен каждой дате. Для этого сгенерим таблицу с полным список дат и объединим с полученной. Для генерации списка дат создадим пустой запрос:
И отредактируем код запроса вручную в Расширенном редакторе:
Зададим границы диапазона данных — дату начала и дату окончания:
date_start = #date(2015, 1, 1),
date_end = #date(2023, 1, 1),
Воспользуемся List.Dates для генерации списка дат. Ей необходимо три параметра: дата старта диапазона, количество элементов и шаг:
date_list = List.Dates(
date_start,
Duration.Days(date_end — date_start) + 1,
#duration(1, 0, 0, 0)
)
Получим вот такой код:
let
date_start = #date(2015, 1, 1),
date_end = #date(2023, 1, 1),
date_list = List.Dates(
date_start,
Duration.Days(date_end — date_start) + 1,
#duration(1, 0, 0, 0)
)
in
date_list
И в результате получим вот список дат в заданном диапазоне. Это список (не таблица) и, соответственно, не имеет всех атрибутов таблицы. Преобразуем его в таблицу:
А вот это уже таблица. Переименуем, изменим типа данных на Date:
Получаем таблицу со списком дат, но без указания типов этих дат. “Вытащим” типы данных из первой созданной таблицы. Для этого объединим таблицы:
Если мы вызвали команду объединения, находясь во второй таблице, то эта вторая таблица автоматически встанет в качестве первой объединяемой таблицы. Нам нужно выбрать вторую — это данные, загруженные с Портала открытых данных. Необходимо указать, по каким столбцам сопоставлять данные — выбираем в обеих таблицах колонку Date:
Для каждой строки создалась подтаблица из данных присоединённой таблицы. Развернём колонки:
Снимем галочку использования названия таблицы в качестве префикса, снимем галочку со столбца Date:
В результате получим таблицу, у которой будут проставлены типы дат у выходных и сокращённых рабочих дней. У части дат будет null вместо типа даты. Исходя из логики загруженного производственного календаря делаем вывод, что это простые рабочие дни. Заменим null на слово “Рабочий”:
Вот теперь — всё. Осталось только загрузить
Итоговый код второго запроса:
let
date_start = #date(2015, 1, 1),
date_end = #date(2023, 1, 1),
date_list = List.Dates(
date_start,
Duration.Days(date_end — date_start) + 1,
#duration(1, 0, 0, 0)
),
#»Преобразовано в таблицу» = Table.FromList(date_list, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#»Переименованные столбцы» = Table.RenameColumns(#»Преобразовано в таблицу»,{{«Column1», «Date»}}),
#»Измененный тип» = Table.TransformColumnTypes(#»Переименованные столбцы»,{{«Date», type date}}),
#»Объединенные запросы» = Table.NestedJoin(#»Измененный тип», {«Date»}, #»data-20191112T1252-structure-20191112T1247″, {«Date»}, «data-20191112T1252-structure-20191112T1247», JoinKind.LeftOuter),
#»Развернутый элемент data-20191112T1252-structure-20191112T1247″ = Table.ExpandTableColumn(#»Объединенные запросы», «data-20191112T1252-structure-20191112T1247», {«Date type»}, {«Date type»}),
#»Замененное значение» = Table.ReplaceValue(#»Развернутый элемент data-20191112T1252-structure-20191112T1247″,null,»Рабочий»,Replacer.ReplaceValue,{«Date type»})
in
#»Замененное значение»
Подробная инструкция так же в видео.
В одном из заказов недавно столкнулся с проблемой получения праздничных дней согласно утвержденному производственному календарю. Да, я знаю, что в компаниях он может быть свой, отличный от опубликованного государством. И смысла как-то получать список праздничных дат с общедоступных порталов не было. Но вот именно сейчас потребовался именно общедоступный опубликованный календарь, чтобы можно было его автоматом скачать и применить. И оказалось, что это тоже не самая простая задача: многие календари в сети либо в формате PDF, либо в виде frame-ов по месяцам, либо вообще картинками. Только на одном сайте получилось найти файл для скачивания: https://data.gov.ru/opendata/7708660670-proizvcalendar. Но и там оказалась не сразу ссылка на готовый календарь, а описание набора, потом паспорт и уже только в паспорте набора можно найти ссылку на файл:
эта ссылка нам и нужна. И тут две проблемы:
Для рабочего проекта я выбрал способ получения дат через VBA(для поддержки всех версий независимо от надстроек), но в связи с популярностью Power Qwery решил сделать решение и при помощи этой надстройки.
Я постарался в коде в некоторых местах прописать комментарии, т.к. прописывать их напрямую в статье не очень удобно — код не маленький и описывать каждый кусок проблематично и больше запутает, чем прояснит процесс, как мне кажется.
'--------------------------------------------------------------------------------------- ' Author : Дмитрий (The_Prist) Щербаков ' Профессиональная разработка приложений для MS Office любой сложности ' Проведение тренингов по MS Excel ' https://www.excel-vba.ru ' info@excel-vba.ru ' WebMoney - R298726502453; Яндекс.Деньги - 41001332272872 ' Purpose: Загрузка праздничных дат из производственного календаря с сайта data.gov.ru ' https://www.excel-vba.ru/chto-umeet-excel/proizvodstvennyj-kalendar-v-excel-vba-i-power-qwery/ '--------------------------------------------------------------------------------------- Option Explicit 'объявление функции API - URLDownloadToFile для скачивания файла 'Идет в самом начале, т.к. API функции необходимо объявлять именно здесь ' работает на любых ПК под управлением ОС Windows ' на MAC код работать не будет #If Win64 Then 'для операционных систем с 64-разрядной архитектурой Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _ (ByVal pCaller As LongLong, ByVal szURL As String, ByVal szFileName As String, _ ByVal dwReserved As LongLong, ByVal lpfnCB As LongLong) As LongLong #Else #If VBA7 Then 'для любых операционных систем с офисом 2010 и выше Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _ (ByVal pCaller As LongPtr, ByVal szURL As String, ByVal szFileName As String, _ ByVal dwReserved As Long, ByVal lpfnCB As LongPtr) As LongPtr #Else 'для 32-разрядных операционных систем Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _ (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, _ ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long #End If #End If 'Основная процедура поиска ссылки и скачивания календаря ' в ходе работы использует остальные функции Sub LoadCalendar() Dim res, response$, surl$, sex$, sFName$, sMsg$ Dim oXMLHTTP As Object Dim lp&, le&, le2& Dim wbPrCalendar As Workbook Application.ScreenUpdating = False Err.Clear On Error GoTo err_handler 'подключаемся к сайту Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP") With oXMLHTTP .Open "GET", "https://data.gov.ru/opendata/7708660670-proizvcalendar", False .send 'ждем пока страница прогрузится Do While .readyState <> 4 DoEvents Loop 'запоминаем исходный код страницы(для поиска ссылки) response = .responseText End With If Len(response) Then 'ищем место с ссылкой на наш CSV ' их там несколько, нам нужна "Гиперссылка (URL) на набор" lp = InStr(1, response, "Гиперссылка (URL) на набор", 1) If lp > 0 Then 'если нашли - ищем начало гиперссылки для скачивания(по ключевым http) le = InStr(lp, response, "http", 1) If le > 0 Then 'если это CSV - берем его le2 = InStr(le, response, ".csv", 1) 'CSV не нашли - пробуем найти xlsx(что вряд ли, но лушче попробовать) If le2 = 0 Then le2 = InStr(le, response, ".xls", 1) End If If le2 > 0 Then 'формируем только адрес ссылки для скачивания lp = InStr(le2, response, Chr(34), 1) surl = Mid(response, le, lp - le) lp = InStrRev(surl, ".") sex = Mid(surl, lp, Len(surl) - lp + 1) 'пробуем скачать при помощи функции API Set wbPrCalendar = CallDownload(surl, "prod_cal" & sex) 'обрабатываем скачанный файл If Not wbPrCalendar Is Nothing Then wbPrCalendar.Activate sFName = wbPrCalendar.FullName 'преобразуем данные в файле в столбец дат Call FillProdCalend(wbPrCalendar) wbPrCalendar.Close 0 DoEvents On Error Resume Next 'удаляем после обработки Kill sFName Err.Clear DoEvents sMsg = "Производственный календарь успешно обновлен" End If End If End If End If End If 'если будет какая-то ошибка - код перейдет сюда и покажет текст ошибки err_handler: If Err.Number <> 0 Then sMsg = "Не удалось обновить Производственный календарь." & vbNewLine & _ "Ошибка: " & Err.Description End If Application.ScreenUpdating = True MsgBox sMsg, vbInformation, "www.excel-vba.ru" End Sub '--------------------------------------------------------------------------------------- ' File : mDownloadFileFromURL ' Purpose: код позволяет скачивать файлы из интернета по указанной ссылке ' https://www.excel-vba.ru/chto-umeet-excel/kak-skachat-fajl-iz-interneta-po-ssylke/ '--------------------------------------------------------------------------------------- Function CallDownload(sFileURL As String, sFileName As String) As Workbook 'переменная для хранения пути к папке Dim sFilePath As String, ToPathName As String Dim h sFilePath = Environ("temp") If Right(sFilePath, 1) <> "" Then sFilePath = sFilePath & "" ToPathName = sFilePath & sFileName 'проверяем есть ли файл с таким же именем в выбранной папке If Dir(ToPathName, 16) <> "" Then On Error Resume Next Kill ToPathName DoEvents On Error GoTo 0 End If 'если не возникло ошибок при удалении файла - скачиваем его по ссылке ' если ошибка была - значит такой файл уже открыт ' и в дальнейшем все равно получим ошибку If Err.Number = 0 Then 'вызов функции API для непосредственно скачивания h = (URLDownloadToFile(0, sFileURL, ToPathName, 0, 0) = 0) 'если h = False - файл не удалось скачать, показываем инф.окно If h = False Then MsgBox "Невозможно скачать файл." & vbNewLine & _ "Возможно, у Вас нет прав на создание файлов в папке '" & sFilePath & "'.", _ vbInformation, "www.excel-vba.ru" Set CallDownload = Nothing Exit Function Else 'файл успешно скачан If IsBookOpen(sFileName) Then MsgBox "Файл с именем '" & sFileName & "' уже открыт. Закройте открытый файл и повторите попытку.", vbCritical, "www.excel-vba.ru" Else Set CallDownload = Application.Workbooks.Open(ToPathName) End If End If Else Set CallDownload = Nothing End If End Function 'функция заполнения листа "ProdCalend" датами из производственного календаря ' предварительно функция разбивает даты на отдельные ' т.к. изначально они записаны в виде перечня дней для каждого месяца Function FillProdCalend(wbCSV As Workbook) Dim acsv, ares() Dim dic As Object Dim llastr&, lr&, lc&, lcnt& Dim ly&, lm&, ld& Dim asp, sd$, s$, x Dim dt As Date With wbCSV.Worksheets(1) llastr = .Cells(.Rows.Count, 1).End(xlUp).Row acsv = .Cells(1, 1).Resize(llastr, 13).Value End With With ThisWorkbook.Sheets("ProdCalend") 'очищаем лист от старых данных .Columns(1).Cells.Clear 'здесь будем хранить список уникальных дат Set dic = CreateObject("scripting.dictionary") dic.comparemode = 1 'просматриваем каждую строку файла(год), начиная со 2-й For lr = 2 To UBound(acsv, 1) If IsNumeric(acsv(lr, 1)) Then ly = Val(Trim(acsv(lr, 1))) 'просматриваем каждый столбец файла(месяц), начиная со 2-го For lc = 2 To UBound(acsv, 2) lm = lc - 1 s = acsv(lr, lc) s = Trim(s) 'убираем символы + 'которыми обозначаются перенесенные праздничные дни s = Replace(s, "+", "") If Len(s) Then 'разбиваем единую строку вида 1,2,3,4,6*,7,9,10,16,17,23,24,30,31 'на отдельные дни asp = Split(s, ",") 'перебор каждого дня и создание из него даты 'с запоминанием в словарь дат dic For Each x In asp s = Trim(x) 'не учитываем даты со знаком * - это сокращенные предпраздничные дни If InStr(1, s, "*", 1) = 0 Then If Len(s) Then ld = Val(s) dt = DateSerial(ly, lm, ld) If Not dic.exists(dt) Then dic.Add dt, 0& End If End If End If Next End If Next End If Next 'даты есть - записываем на лист ' можно было поступить проще ' .Cells(2, 1).Resize(dic.Count).Value = Application.Transpose(dic.Keys) ' но этот метод опасен тем, что порой может выгрузить не все данные ' хотя в данном конкретном случае это очень маловероятно, т.к. ограничения касаются ' кол-ва строк в 65536 и текста в каждой строке до 255 символов If dic.Count > 0 Then ReDim ares(1 To dic.Count, 1 To 1) lr = 0 For Each x In dic.keys lr = lr + 1 ares(lr, 1) = x Next .Cells(1, 1).Value = "Праздники и выходные" .Cells(2, 1).Resize(dic.Count).Value = ares End If End With End Function 'Функция проверки - открыта ли книга с заданным именем 'подробнее: ' https://www.excel-vba.ru/chto-umeet-excel/kak-proverit-otkryta-li-kniga/ Function IsBookOpen(wbName As String) As Boolean Dim wbBook As Workbook For Each wbBook In Workbooks If Windows(wbBook.Name).Visible Then If wbBook.Name = wbName Then IsBookOpen = True: Exit For End If Next wbBook End Function
Чтобы использовать код необходимо создать файл Excel, в этом файле создать лист с именем «ProdCalend». Далее переходим в редактор VBA(Alt+F11) —Insert —Module. Вставляем туда код выше полностью. Или скачать файл ниже — там уже все сделано удобно и красиво:
Скачать файл с кодом:
В случае с Power Qwery все с одной стороны проще, а с другой есть свои нюансы. Взять хотя бы попытку получить напрямую текст страницы https://data.gov.ru/opendata/7708660670-proizvcalendar: если попытаться подключиться через стандартный метод(Другие(Other) —Из интернета(from Web), то придется очень долго разворачивать элемент Document на составные части разметки HTML в поисках тегов DIV и A для определения строки с гиперссылкой. Что на мой взгляд не оптимально и уж совсем не гибко — любое изменение структуры страницы, даже малейшее может привести к ошибке.
Поэтому я использовал менее очевидный, но куда более удобный в данном случае вариант — Lines.FromBinary(Web.Contents(«https://data.gov.ru/opendata/7708660670-proizvcalendar»)). Это самая важная строка в текущей задаче — она получает исходный текст страницы сайта в виде разбитого на строки текста, в котором потом можно будет просматривать и искать нужное нам
а дальше по сути идет тоже самое, что делалось кодом VBA: ищем в этом тексте ссылку, выдергиваем только ссылку для скачивания файла календаря, подключаемся к этой ссылке для получения конечного CSV и делаем преобразования. Только это выглядит куда проще и заметно короче, чем тоже самое на VBA Сам код из расширенного редактора:
let //получаем исходный текст страницы в виде разбитого на строки текста Source = Table.FromColumns({Lines.FromBinary(Web.Contents("https://data.gov.ru/opendata/7708660670-proizvcalendar"))}), //отбираем из строк ту, которая содержит внутри текст "Гиперссылка (URL) на набор" и ".csv" и превращаем все это в строку // т.к. изначально Table.SelectRows возвращает набор в виде таблицы CsvURLText = Table.SelectRows(Source, each Text.Contains([Column1], "Гиперссылка (URL) на набор") and Text.Contains([Column1], ".csv")){0}[Column1], //ищем начало гиперссылки url_start_pos = Text.PositionOf(CsvURLText,"http"), //ищем конец гиперссылки url_end_pos = Text.PositionOf(CsvURLText,".csv"), //формируем гиперссылку из CsvURLText url = Text.Middle(CsvURLText,url_start_pos,url_end_pos-url_start_pos+4), //скачиваем файл CSV по сформированной гиперссылке и открываем его //в заголовках будут имена месяцев csvfile = Table.PromoteHeaders(Csv.Document(Web.Contents(url),[Delimiter=",", Columns=18, Encoding=65001, QuoteStyle=QuoteStyle.None]), [PromoteAllScalars=true]), //сворачиваем столбцы с датами в два столбца: название месяца("Атрибут") и перечень дат("Значение") #"Несвернутые столбцы" = Table.UnpivotOtherColumns(csvfile, {"Год/Месяц", "Всего рабочих дней", "Всего праздничных и выходных дней", "Количество рабочих часов при 40-часовой рабочей неделе", "Количество рабочих часов при 36-часовой рабочей неделе", "Количество рабочих часов при 24-часовой рабочей неделе"}, "Атрибут", "Значение"), //убираем символы +, которыми обозначаются перенесенные праздничные дни #"Замененное значение1" = Table.ReplaceValue(#"Несвернутые столбцы","+","",Replacer.ReplaceText,{"Значение"}), //разбиваем столбец с днями на отдельные столбцы #"Разделить столбец по разделителю" = Table.SplitColumn(#"Замененное значение1", "Значение", Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), {"Значение.1", "Значение.2", "Значение.3", "Значение.4", "Значение.5", "Значение.6", "Значение.7", "Значение.8", "Значение.9", "Значение.10", "Значение.11", "Значение.12", "Значение.13", "Значение.14", "Значение.15", "Значение.16"}), //сворачиваем все столбцы с днями в два: "Атрибут.1"(нам не нужен) и день("Значение") #"Другие столбцы с отмененным свертыванием" = Table.UnpivotOtherColumns(#"Разделить столбец по разделителю", {"Год/Месяц", "Всего рабочих дней", "Всего праздничных и выходных дней", "Количество рабочих часов при 40-часовой рабочей неделе", "Количество рабочих часов при 36-часовой рабочей неделе", "Количество рабочих часов при 24-часовой рабочей неделе", "Атрибут"}, "Атрибут.1", "Значение"), //удаляем все строки с сокращенными днями #"Строки с примененным фильтром" = Table.SelectRows(#"Другие столбцы с отмененным свертыванием", each not Text.Contains([Значение], "*")), //в отдельном столбце формируем из столбцов с годом, месяцем и днем дату #"Добавлен пользовательский объект" = Table.AddColumn(#"Строки с примененным фильтром", "Пользовательский", each Date.FromText([Значение] & " " & [Атрибут] & " " & [#"Год/Месяц"],"Ru-ru")), //переименовываем столбец #"Переименованные столбцы" = Table.RenameColumns(#"Добавлен пользовательский объект",{{"Пользовательский", "Дата"}}), //удаляем лишние столбцы(по сути все, кроме столбца дата) #"Другие удаленные столбцы" = Table.SelectColumns(#"Переименованные столбцы",{"Дата"}), //преобразуем тип Any(Любой) в тип Дата #"Измененный тип" = Table.TransformColumnTypes(#"Другие удаленные столбцы",{{"Дата", type date}}) in #"Измененный тип"
Так же не стал расписывать со скринами по шагам все преобразования, т.к. каждый желающий может скачать файл(приложен ниже) с запросом PQ и просмотреть по шагам все действия:
Но если вдруг это надо будет — пишите в комментариях, постараюсь описать процесс наглядно(в будущем подготовлю видеоурок на данную тему).
Производственный календарь (или календарь рабочих и праздничных дней) – одна из важных составляющих многих отчетов и инструментов планирования.
Из-за “плавающих” выходных и праздничных дней в России мы не можем каждый год использовать один и тот же набор данных.
Лично у меня ежегодно возникает вопрос – где скачать производственный календарь. Желательно в удобном формате Excel и с наименьшими трудозатратами. И вот совсем недавно я нашёл для себя решение, которое, уверен, пригодится многим.
Для автоматизации процесса нам понадобится
- Microsoft Excel (2010, 2013 или 2016)
- Страничка на портале Открытых Данных России откуда можно скачать производственный календарь в csv формате: http://data.gov.ru/opendata/7708660670-proizvcalendar.
* для Excel 2010 и 2013 вам понадобится бесплатная надстройка Power Query, скачать можно отсюда.
Как страничка выглядит на момент написания данной статьи – возможность скачать актуальную версию проиводственного календаря
На странице так же доступны предыдущие версии и версия производственного календаря в xlsx:
В Excel 2016 для решения подобных задач у нас есть группа кнопок “Скачать и преобразовать” (Get & Transform) на закладке меню “Данные” (Data).
Для Excel 2010 и Excel 2013 такой же функционал доступен в виде бесплатной надстройки Power Query, можно скачать отсюда. Функционал надстройки развивается каждый месяц, я рекомендую регулярно обновляться, чтобы всегда иметь под рукой новейшие функции и возможности трансформации данных.
Когда все нужные программы установлены и источник информации исследован – вернемся к задаче.
Для скачивания чего-либо из Интернета нам нужна ссылка на файл или страницу.
Портал открытых данных публикует наборы данных и обязательно сопровождает каждый набор Паспортом.
Паспорт содержит важную информацию о наборе, из которой, в частности, мы можем взять “Гиперссылку (URL) на набор данных”
Скопируем URL и сделаем запрос “Из интернета”.
Вставляем ссылку на csv файл
Далее – выберем кодировку 65001 UTF-8, игнорируем авто-определение типов данных и жмём “Изменить”
Теперь необходимо преобразовать полученные данные.
- Используем первую строку в качестве заголовков столбцов
-
Выберем нужные нам столбцы. Воспользуемся функцией “Выбор столбцов” (Select Columns)
-
Для удобства фильтрации изменим формат столбца “Год/Месяц” на “Целое число”
-
Воспользуемся фильтром, оставим только интересующие нас годы
Зададим фильтр с нужными нам условиями
-
Переименуем столбцы в порядковые номера месяцев и “Год/Месяц” в “Год”
-
Далее воспользуемся функцией “Отменить свёртывание других столбцов” (Unpivot Other Columns) доступной на закладке меню “Преобразование” (Transform), выделив предварительно столбец “Год”
-
Теперь выделим столбец “Значение” и разделим его на столбцы по разделителю “запятая”.
Это действие превращает таблицу в нечто ужасное с кучей столбцов. К тому же возникает непрошенный шаг – “Измененный тип1”, который нужно удалить.
Чтобы привести таблицу в нормальный вид, еще раз воспользуемся функцией “Отменить свертывание других столбцов” (Unpivot Other Columns)
-
Выделяем столбцы “Год” и “Атрибут” (далее его переименуем в месяц)
В результате получается таблица
- Удаляем столбец “Атрибут.1” образованный из заголовков столбцов
-
Среди значений выходных и праздничных дней опубликованный календарь содержит предпраздничные дни. В некоторых сценариях их важно учитывать, так как в эти дни количество рабочих часов сокращено.
Но если интерес представляют только нерабочие дни, то дни со звёздочкой нужно исключить из списка. Это можно сделать простым фильтром “не содержит” символ “*”
-
Осталась пара штрихов – переименовать столбцы и установить корректный тип данных
- В заключение можно добавить столбец с датой
Используем формулу
- Получив столбец с датой, можно убрать предыдущие столбцы
-
Важно установить корректный тип данных!
-
Осталось сохранить запрос и можно выводить его на лист
Подобным запросом мы получаем не полный список календарных дат, так как публикуемый на портале Открытых Данных набор содержит только праздничные и предпраздничные дни.
Полученный список может быть использован в функциях РАБДЕНЬ (WORKDAY), РАБДЕНЬ.МЕЖД (WORKDAY.INTL), а также для разметки полного календаря рабочими / не рабочими днями (что актуально для моделей в Power Pivot и Power BI).
Как обращаться к наиболее актуальному набору данных
Благодаря тому, что есть HTML представление паспорта данных на странице http://data.gov.ru/node/19107/code-passport
к нему тоже можно сделать запрос из Power Query (“Скачать и Преобразовать” / Get & Transform)
Интерес представляет блок со словами “Гиперссылка (URL) на набор”. Именно эта строка содержит ссылку на наиболее актуальный набор.
Разобраться, как это работает, вы можете, изучив xlsx-файл доступный по ссылке.
В нём вы найдёте несколько запросов
Для упрощения жизни разработчиков моделей в Power Pivot и Power BI, запрос на получение списка выходных дней доступен в виде функции в моей коллекции функций на Github – List.Dates.HolidaysRU
Если вы знаете, где можно найти такую же официальную информацию для СНГ стран, в частности, Казахстана, Украины и Республики Беларусь, оставьте комментарий со ссылкой. А ещё лучше – pull request в проект с соответствующими функциями.