Vba excel рабочий день

title keywords f1_keywords ms.prod api_name ms.assetid ms.date ms.localizationpriority

WorksheetFunction.WorkDay method (Excel)

vbaxl10.chm137347

vbaxl10.chm137347

excel

Excel.WorksheetFunction.WorkDay

358c358f-c76e-1309-4a2f-8e50f8d7e7d9

05/25/2019

medium

WorksheetFunction.WorkDay method (Excel)

Returns a number that represents a date that is the indicated number of working days before or after a date (the starting date). Working days exclude weekends and any dates identified as holidays. Use WorkDay to exclude weekends or holidays when you calculate invoice due dates, expected delivery times, or the number of days of work performed.

Syntax

expression.WorkDay (Arg1, Arg2, Arg3)

expression A variable that represents a WorksheetFunction object.

Parameters

Name Required/Optional Data type Description
Arg1 Required Variant Start_date — a date that represents the start date.
Arg2 Required Variant Days — the number of nonweekend and nonholiday days before or after start_date. A positive value for days yields a future date; a negative value yields a past date.
Arg3 Optional Variant Holidays — an optional list of one or more dates to exclude from the working calendar, such as state and federal holidays and floating holidays. The list can be either a range of cells that contain the dates or an array constant of the serial numbers that represent the dates.

Return value

Double

Remarks

[!IMPORTANT]
Dates should be entered by using the DATE function, or as results of other formulas or functions. For example, use DATE(2008,5,23) for the 23rd day of May, 2008. Problems can occur if dates are entered as text .

Microsoft Excel stores dates as sequential serial numbers so they can be used in calculations. By default, January 1, 1900 is serial number 1, and January 1, 2008 is serial number 39448 because it is 39,448 days after January 1, 1900. Microsoft Excel for the Macintosh uses a different date system as its default.

[!NOTE]
Visual Basic for Applications (VBA) calculates serial dates differently than Excel. In VBA, serial number 1 is December 31, 1899, rather than January 1, 1900.

If any argument is not a valid date, WorkDay returns the #VALUE! error value.

If start_date plus days yields an invalid date, WorkDay returns the #NUM! error value.

If days is not an integer, it is truncated.

[!includeSupport and feedback]

Определяем день ( рабочий или выходной)

cekist

Дата: Воскресенье, 17.09.2017, 23:10 |
Сообщение № 1

Группа: Пользователи

Ранг: Новичок

Сообщений: 12


Репутация:

0

±

Замечаний:
0% ±


Excel 2013

Доброго времени суток! Возник вопрос как определить рабочие и выходные дни, при наличии столбца с датами (рабочие дни понедельник пятница, выходные соответственно суббота воскресенье).
Проблема также возникает и в том, что в разных файлах разное количество строк.
Возможно прописать в макросе VBA чтобы рядом с датой, в другом столбце автоматически указывало день недели и в соседнем выходной день или рабочий.
Большое спасибо за помощь!!!

К сообщению приложен файл:

5253740.xlsx
(53.0 Kb)

 

Ответить

_Igor_61

Дата: Воскресенье, 17.09.2017, 23:50 |
Сообщение № 2

Группа: Проверенные

Ранг: Ветеран

Сообщений: 504


Репутация:

90

±

Замечаний:
0% ±


Excel 2007

Здравствуйте! А формулами можно?

К сообщению приложен файл:

7887989.xlsx
(98.3 Kb)

 

Ответить

_Igor_61

Дата: Понедельник, 18.09.2017, 00:15 |
Сообщение № 3

Группа: Проверенные

Ранг: Ветеран

Сообщений: 504


Репутация:

90

±

Замечаний:
0% ±


Excel 2007

Ну и те же формулы макросом записал :)

К сообщению приложен файл:

7962716.xlsm
(68.4 Kb)

 

Ответить

Che79

Дата: Понедельник, 18.09.2017, 00:28 |
Сообщение № 4

Группа: Друзья

Ранг: Старожил

Сообщений: 1649


Репутация:

306

±

Замечаний:
0% ±


2013 Win, 365 Mac

Вариант +формат ячеек «Выходной»;;»Рабочий»

PS
Вот это не сразу увидел

в другом столбце автоматически указывало день недели

и формат ДДД


Делай нормально и будет нормально!

Сообщение отредактировал Che79Понедельник, 18.09.2017, 00:37

 

Ответить

cekist

Дата: Понедельник, 25.09.2017, 22:24 |
Сообщение № 5

Группа: Пользователи

Ранг: Новичок

Сообщений: 12


Репутация:

0

±

Замечаний:
0% ±


Excel 2013

Ну и те же формулы макросом записал
К сообщению приложен файл: 7962716.xlsm(68Kb)

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

 

Ответить

Kuzmich

Дата: Понедельник, 25.09.2017, 22:47 |
Сообщение № 6

Группа: Проверенные

Ранг: Ветеран

Сообщений: 707


Репутация:

154

±

Замечаний:
0% ±


Excel 2003

Цитата

он преобразовывает только первые 10000 ячеек

В макросе есть строка
[vba]

Код

Range(«B2:C2»).AutoFill Destination:=Range(«B2:C10000»)

[/vba]
Вместо 10000 поставьте свой диапазон

 

Ответить

 

aequit

Пользователь

Сообщений: 209
Регистрация: 13.01.2020

#1

17.01.2020 10:45:20

Здравствуйте!
Разбирался с функцией РАБДЕНЬ, возникла необходимость написания данной функции на чистом VBA без использования дополнительных формул и диапазонов на рабочих листах книги. Выкладываю свой вариант

для закидывания тапками

, может кому пригодится. Можно разместить в личной книге макросов или надстройке. В конце года после выхода постановления Правительства РФ необходимо добавлять в код данные по праздничным и выходным дням, а также по рабочим субботам (внесены данные с 01.01.2015 по текущий год).

Скрытый текст

Прикрепленные файлы

  • Пример функции ближайший рабочий день на VBA.xlsm (24.55 КБ)

Изменено: aequit17.01.2020 11:13:53

 

Jack Famous

Пользователь

Сообщений: 10848
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

aequit, здравствуйте!
Если выкладываете код, то желательно размещать его не только в файле, но и в сообщении (сначала оформить тэгом <…> и под спойлер SP)

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

Тоже такое делал, но что по мне, то более userfriendly делать именно с возможностью указания диапазонов праздников и рабочих суббот(я делал через именованные диапазоны), т.к. в разных компаниях эти даты могут отличаться.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

egonomist

Пользователь

Сообщений: 409
Регистрация: 21.12.2012

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

Сейчас появился еще

один вариант

, используя веб-запрос,  даже

R пакет

сделали с его использованием.
Но пока непонятно как быстро и как долго будут обновлять данные о выходных днях.

 

aequit

Пользователь

Сообщений: 209
Регистрация: 13.01.2020

#5

17.01.2020 14:03:27

Цитата
egonomist написал:
во вложении макрос собирающий все выходные дни

Спасибо, работает (только предварительно нужно создать в книге лист с именем «temp», иначе макрос вываливается в ошибку.
В данном варианте можно обойтись без отдельного списка рабочих суббот, так как после работы макроса в массиве «всех выходных» просто не оказывается рабочих суббот (проверил на 09.06.2018 и 29.12.2018). Также можно исключить проверку на субботы и воскресенья, так как ВСЕ даты, не входящие в список, будут рабочими.

 

Jack Famous

Пользователь

Сообщений: 10848
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

#6

17.01.2020 14:48:48

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

Цитата
Дмитрий(The_Prist) Щербаков: более userfriendly делать именно с возможностью указания диапазонов праздников

можно сделать этот аргумент-диапазон опциональным и, если он не указан, то использовать встроенный справочник, а если указан, то заменить/дополнить список. Типа компромисс. Но за каждый такой компромисс придётся расплачиваться скоростью…

Изменено: Jack Famous17.01.2020 14:49:43

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

aequit

Пользователь

Сообщений: 209
Регистрация: 13.01.2020

#7

18.01.2020 20:43:03

Цитата
Jack Famous написал:
Вместо цикла по массиву праздников, загоняем список в словарь. Метод Exists позволит проверить наличие даты в словаре сильно быстрее. Можно пойти далее и держать словарь в памяти, чтобы не создавать его для каждого вызова функции — будет совсем круто

Сделал.

Цитата
Jack Famous написал:
сделать этот аргумент-диапазон опциональным и, если он не указан, то использовать встроенный справочник, а если указан, то заменить/дополнить список. Типа компромисс.

Сделал.

Скрытый текст

Цитата
Jack Famous написал:
Но за каждый такой компромисс придётся расплачиваться скоростью…

Измерил скорость работы путём заполнения формулой с функцией 500000 ячеек в столбце (при этом происходил её расчёт в каждой ячейке) .
Результаты:
8,296875 секунд, если держать словарь в памяти.
275,9766 секунд, если создавать его для каждого вызова функции.
Ускорение более, чем в 33 раза.
В старом варианте функции из вчерашнего поста, при переборе элементов массива (без словаря) — 61,625 секунд.

Прикрепленные файлы

  • Пример функции ближайший рабочий день на VBA v.2.xlsm (40.35 КБ)

 

Jack Famous

Пользователь

Сообщений: 10848
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

aequit, рад, что помогло  ;)
Если заменить функцию рабочего листа на обработку внутри процедуры с последующей вставкой на лист, то будет ещё заметно быстрее

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

lizardjazz1

Пользователь

Сообщений: 1
Регистрация: 24.01.2020

Доброго времени суток, а можно ли как-то подсчитать рабочее время, например рабочий день с 8 до 18, я изначально делал это формулой, вроде считает, но потом когда к четвергу прибавляется два, три дня, он не переносит на понедельник, а ещё может поставить время позже 18 или раньше 8

Так вот, как можно бы добавить в эту функцию ещё и счёт времени, натолкните на мысль?

Прикрепленные файлы

  • Снимок.JPG (114.74 КБ)

 

aequit

Пользователь

Сообщений: 209
Регистрация: 13.01.2020

#10

25.01.2020 09:01:30

Цитата
lizardjazz1 написал:
как можно бы добавить в эту функцию ещё и счёт времени

Непонятно, что Вы хотите получить? Попробуйте человеку, незнакомому с Вашей задачей (например, коллеге за соседним столом) дать прочитать её и потом спросите: «Понятно и доходчиво я описал требуемое?»
Прибавить к двум рабочим дням 3 рабочих часа? А к какому моменты прибавлять часы?
Опишите подробно и приложите пример, никто за Вас файл рисовать не будет.
В файле сделайте 2 столбца со значениями, в первом исходные данные, во втором — что нужно получить. Тогда шанс получить ответ значительно возрастёт.

 

БМВ

Модератор

Сообщений: 21378
Регистрация: 28.12.2016

Excel 2013, 2016

#11

25.01.2020 09:41:18

Цитата
aequit написал:
Непонятно, что Вы хотите получить?

непонятно не это, a то как вопрос связан с начальной темой  :D

По вопросам из тем форума, личку не читаю.

 

ближайший рабочий день он и без VBA ближайший рабочий день, только очень сильно зависит от праздников страны в которой вы живете.

Изменено: Ігор Гончаренко25.01.2020 09:41:49

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

aequit

Пользователь

Сообщений: 209
Регистрация: 13.01.2020

#13

25.01.2020 09:45:41

Цитата
Ігор Гончаренко написал:
зависит от праздников страны

Еще и от региона страны. Ближайший пример: у нас в области 28 декабря 2019 года был объявлен рабочим днём, а 31 декабря 2019 года — выходным.
В 2018 году дни проведения матчей чемпионата мира по футболу в нашей области были объявлены выходными днями. Всё это оперативно нужно учитывать.

 

да, я именно об этом
если этой информации нет в исходных, ничего считать НЕ ВОЗМОЖНО, т.е. можно но без толку. поэтому задача больше на экстрасенсов, чем на людей что-то понимающих в Excel

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

DimasAda

Пользователь

Сообщений: 2
Регистрация: 10.02.2021

#15

11.02.2021 12:24:41

Цитата
aequit написал:
дравствуйте!Разбирался с функцией РАБДЕНЬ, возникла необходимость написания данной функции на чистом VBA без использования дополнительных формул и диапазонов на рабочих листах книги. Выкладываю свой вариант для закидывания тапками, может кому пригодится. Можно разместить в личной книге макросов или надстройке. В конце года после выхода постановления Правительства РФ необходимо добавлять в код данные по праздничным и выходным дням, а также по рабочим субботам (внесены данные с 01.01.2015 по текущий год).

Добрый день. Дублирую сюда еще.
Понравилась реализация функции  

https://www.cyberforum.ru/blogs/307973/blog6287.html
https://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&FID=1&TID=124610&TITLE_SEO=124610-funktsiya-blizhayshiy-rabochiy-den-na-vba&MID=1029227#message1029227

Доработал для чтения массива выходных из диапазона ячеек, но не смог победить одну проблему:
При вводе значения в «iДобавитьДней» меньше единицы 0,2; 0,5; 0,8… выполняется расчет без учета остатка дня.

Прошу помочь с поиском решения

 

aequit

Пользователь

Сообщений: 209
Регистрация: 13.01.2020

#16

11.02.2021 16:13:23

Цитата
DimasAda написал:
Прошу помочь с поиском решения

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

VBA

 

Почему-то ругается на «new dictionary» в модуле в моем файле, выдает ошибку invalid use of new keyword site:stackoverflow.com

 

aequit

Пользователь

Сообщений: 209
Регистрация: 13.01.2020

Сергей bangoo,
Может microsoft scripting runtime не подключен?

 

Подключен, разобрался, была подключена библотека вордовская которая была выше в иерархии и перехватывала dictionary.
Еще вопрос, если вводимая дата — рабочий день, то функция все равно ищет ближайший рабочий?

 

aequit

Пользователь

Сообщений: 209
Регистрация: 13.01.2020

#20

19.09.2022 08:24:52

Цитата
Сергей bangoo написал:
если вводимая дата — рабочий день, то функция все равно ищет ближайший рабочий?

Да, это и требуется.
Кроме вводимой даты есть ещё один аргумент: количество дней.
Вводим дату 19.09.2022 и количество дней — 1. Результат будет 20.09.2022
Вводим дату 19.09.2022 и количество дней — 0. Результат будет 19.09.2022

Содержание

  • Обзор функции РАБДЕНЬ
  • РАБДЕНЬ Синтаксис и входные данные функции:
  • Найти ближайший рабочий день
  • РАБДЕНЬ в Google Таблицах
  • WORKDAY Примеры в VBA

Скачать пример рабочей книги

Загрузите образец книги

В этом руководстве показано, как использовать Функция РАБДЕНЬ в Excel в Excel добавить рабочие дни.

Обзор функции РАБДЕНЬ

Функция РАБДЕНЬ Возвращает рабочий день n количество рабочих дней (рабочие дни, исключая выходные: суббота и воскресенье) с даты начала. По желанию можно исключить праздники. Для нестандартных выходных используйте WORKDAY.INTL.

Чтобы использовать функцию рабочего листа Excel WORKDAY, выберите ячейку и введите:

(Обратите внимание, как появляется ввод формулы)

РАБДЕНЬ Синтаксис и входные данные функции:

1 = РАБДЕНЬ (начальная_дата, дни, праздники)

Дата начала — Дата начала в формате серийного номера Excel или введенная как дата с цитатами вокруг даты. Пример: нельзя вводить 11.12.2015 прямо в ячейку. Вместо этого вам нужно ввести «11/12/2015», или вам нужно будет использовать соответствующий серийный номер: 42320. В качестве альтернативы вы можете указать ячейку с введенной датой 11/12/2015. Excel автоматически преобразует даты, хранящиеся в ячейках, в последовательный формат (если дата не вводится как текст).

дней — Количество не выходных и не выходных дней с даты начала.

каникулы — ПО ЖЕЛАНИЮ. Массив со списком дат, представляющих праздники, которые следует исключить из рабочих дней.

Найти ближайший рабочий день

Чтобы найти ближайший рабочий день, используйте функцию РАБДЕНЬ:

Найти ближайший к сегодняшнему дню рабочий день

Чтобы найти ближайший к сегодняшнему дню рабочий день, используйте функцию СЕГОДНЯ с функцией РАБДЕНЬ:

1 = РАБДЕНЬ (СЕГОДНЯ (); B3)

Найти ближайший рабочий день за 10 дней

В этом примере будет найден ближайший рабочий день через 10 дней от даты начала:

Вы также можете использовать отрицательные дни для поиска рабочих дней в прошлом:

Рабочий день с праздниками

По умолчанию РАБДНИ игнорируют все праздники. Однако вы можете использовать третий необязательный аргумент для определения диапазона праздников:

1 = РАБДЕНЬ (B3; C3; F3: F4)

РАБДЕНЬ в Google Таблицах

Функция РАБДЕНЬ в Google Таблицах работает точно так же, как и в Excel:

WORKDAY Примеры в VBA


Вы также можете использовать функцию РАБДЕНЬ в VBA. Тип:
Application.Worksheetfunction.Workday (начальная_дата, дни, праздники)

Выполнение следующих операторов VBA

123 Диапазон («E2») = Application.WorksheetFunction.WorkDay (Диапазон («B2»), Диапазон («C2»))Диапазон («E3») = Application.WorksheetFunction.WorkDay (Диапазон («B3»), Диапазон («C3»))Диапазон («E4») = Application.WorksheetFunction.WorkDay (Диапазон («B4»), Диапазон («C4»), Диапазон («D4»))

даст следующие результаты


Для аргументов функции (начальная_дата и т. Д.) Вы можете либо ввести их непосредственно в функцию, либо определить переменные для использования вместо них.

Вернуться к списку всех функций в Excel

Вы поможете развитию сайта, поделившись страницей с друзьями

Расчет рабочего времени за период, ограниченный двумя датами, в течение одного года с помощью кода VBA Excel. Функция для расчета рабочего времени.

Календарь рабочего времени

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

Создавать такой календарь вручную, не считая протяжку дат, довольно долго и нудно. Поэтому мы создадим производственный мини-календарь программно.

Для создания календаря рабочего времени из кода VBA Excel сначала следует запустить процедуру DaysOfYear, которая заполнит строку дат:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

Sub DaysOfYear()

Dim y As String, c1 As Range, i As Integer

‘Указываем год, для которого нужна строка дат

y = «2023»

‘Указываем ячейку, в которой будет первый день года

Set c1 = Cells(1, 2)

‘В первую ячейку строки с датами вставляем первый день года

c1 = CDate(«01.01.» & y)

‘Задаем формат отображения даты

c1.NumberFormat = «dd.mm.yy»

‘Заполняем выбранную строку со 2 дня до конца года

    Do While c1.Offset(0, i) <> CDate(«31.12.» & y)

        c1.Offset(0, i + 1) = c1.Offset(0, i) + 1

        c1.Offset(0, i + 1).NumberFormat = «dd.mm.yy»

        i = i + 1

    Loop

‘Присваиваем диапазону дат имя

Range(c1, c1.End(xlToRight)).Name = «Год» & y

End Sub

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

Процедура DaysOfYear запускается из редактора VBA Excel и работает около минуты. Ускорить ее можно, используя массив, который заполняется датами и затем значения его элементов вставляются в диапазон дат.

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

Заполнение строки часов

Допустим, нам нужен календарь с пятидневной 40-часовой рабочей неделей, в котором необходимо указать 8 часов для будничных дней и 0 часов — для выходных.

Заполняем строку рабочего времени из кода VBA Excel с помощью процедуры WorkingTimeDay, которая в ячейки строки времени под ячейками с субботой и воскресеньем вставляет 0, а под ячейками с буднями — 8:

Public Sub WorkingTimeDay()

Dim c As Range

    For Each c In Range(«Год2023»)

        If Weekday(c, vbMonday) = 6 Or Weekday(c, vbMonday) = 7 Then

            c.Offset(1, 0) = 0

        Else

            c.Offset(1, 0) = 8

        End If

    Next

End Sub

Ну и для полной достоверности, следует исключить из группы рабочих праздничные дни, для чего запускаем из редактора VBA Excel следующую процедуру:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

Sub Holidays2023()

‘Нерабочие праздничные дни в 2023 году:

‘с 1 по 8 января — 8 дней;

‘с 23 по 26 февраля — 4 дня;

‘8 марта;

‘с 29 апреля по 1 мая — 3 дня;

‘с 6 по 9 мая — 4 дня;

‘с 10 по 12 июня — 3 дня;

‘с 4 по 6 ноября — 3 дня.

Dim c As Range

    For Each c In Range(«Год2023»)

        Select Case c

            Case CDate(«01.01.2023») To CDate(«08.01.2023»)

                c.Offset(1, 0) = 0

            Case CDate(«23.02.2023») To CDate(«26.02.2023»)

                c.Offset(1, 0) = 0

            Case CDate(«08.03.2023»)

                c.Offset(1, 0) = 0

            Case CDate(«29.04.2023») To CDate(«01.05.2023»)

                c.Offset(1, 0) = 0

            Case CDate(«06.05.2023») To CDate(«09.05.2023»)

                c.Offset(1, 0) = 0

            Case CDate(«10.06.2023») To CDate(«12.06.2023»)

                c.Offset(1, 0) = 0

            Case CDate(«04.11.2023») To CDate(«06.11.2023»)

                c.Offset(1, 0) = 0

        End Select

    Next

End Sub

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

Расчет рабочего времени

Расчет рабочего времени за период, ограниченный двумя датами, будем производить с помощью функции WorkingPeriodHours:

Public Function WorkingPeriodHours(date1, date2)

    If date2 < date1 Or Not IsDate(date1) Or Not IsDate(date2) Then

        WorkingPeriodHours = «Укажите период»

        Exit Function

    End If

Dim i As Integer, d1 As Integer, d2 As Integer, h As Integer

d1 = date1 Range(«Год2023»).Cells(1) + 1

d2 = date2 Range(«Год2023»).Cells(1) + 1

    For i = d1 To d2

        h = h + Range(«Год2023»).Cells(i).Offset(1, 0)

    Next

WorkingPeriodHours = h

End Function

Если в ячейках, являющихся аргументами функции WorkingPeriodHours, будут указаны не даты или даты в неправильном порядке (первая дата больше второй), функция возвратит сообщение: «Укажите период». Если будут указаны неверные даты, не входящие в диапазон дат, функция возвратит значение ошибки: «#ЗНАЧ!».

Код функции размещается в стандартном модуле.

Для вставки в ячейку функция WorkingPeriodHours будет доступна в категории «Определенные пользователем» мастера функций Excel.


Хитрости »

23 Октябрь 2017              10915 просмотров


Проблема получения последнего дня месяца довольно распространена и очень просто решается. Начиная с Excel 2007 можно без всяких доп.манипуляций использовать функцию КОНМЕСЯЦА(EOMONTH):
=КОНМЕСЯЦА(ТДАТА();0)
=EOMONTH(NOW(),0)
ТДАТА(NOW) — возвращает текущую дату. Вместо неё можно указать любую дату и последняя дата месяца будет возвращена для указанной даты.
Для версий 2003 и ранее для использования КОНМЕСЯЦА(EOMONTH) необходимо для начала подключить надстройку Пакет анализа или же использовать чуть менее понятную формулу:
=ДАТА(ГОД(ТДАТА());МЕСЯЦ(ТДАТА())+1;0)
=DATE(YEAR(NOW()),MONTH(NOW())+1,0)
На самом деле данная формула проста, если разобраться детальнее. Функция ДАТА записывает в ячейку дату, на основании указанного года, месяца и дня. Мы для года берем год от текущей даты, далее берем месяц текущей даты и к месяцу прибавляем 1, чтобы получить следующий месяц. А потом для дня указываем 0, что заставляет Excel сдвинуть первую дату следующего месяца на один день назад. Таким образом и получается последняя дата месяца. Пошагово это выглядит так(если считать, что сегодня «22.10.2017»):
=ДАТА(ГОД(ТДАТА());МЕСЯЦ(ТДАТА())+1;0) =>
=ДАТА(ГОД(«22.10.2017»);МЕСЯЦ(«22.10.2017»)+1;0) =>
=ДАТА(2017;10+1;0) =>
=ДАТА(2017;11;0) здесь уже получится 01.11.2017, но 0 в качестве дня заставляет вернуться на день назад =>
=31.10.2017


Но есть более сложная проблема — получить дату последнего рабочего дня месяца. А это уже не так просто. Встроенных функций(вроде КОНМЕСЯЦА) для этого в Excel нет. А это значит опять придется танцевать с бубном.
Сразу возникает вопрос: а зачем это вообще может потребоваться? Например, для поиска счетов, отгрузка по которым производилась в последний рабочий день месяца, а оплаты(или документы на отгрузку) по некоторым пришли только в начале следующего. Так же такую функцию будет удобно применять для автоматического формирования платежек или накладных, если они должны быть оформлены именно последним рабочим днем месяца.
Чтобы получить именно корректную дату следует так же учесть и тот факт, что есть дни праздничные. И их тоже надо как-то учесть. Для этого я буду использовать отдельный лист Праздники, в столбце А которого записаны праздничные дни на пару лет. Также в этом диапазоне перечислены и все выходные. Сделано для более корректного подсчета дат, т.к. праздники могут быть перенесены, в результате чего рабочими становятся субботы или воскресенья. Если их не учитывать, то расчет будет неверным.

Из спортивного интереса создать такую функцию решил тремя способами:

  • При помощи стандартных функций Excel
  • При помощи функции пользователя на VBA
  • При помощи PowerQuery

Последний рабочий день при помощи стандартных функций Excel
В ходе некоторых экспериментов и манипуляций появилась такая формула:
=РАБДЕНЬ(
ЕСЛИ(ДЕНЬНЕД(КОНМЕСЯЦА(B4;0);2)<6; КОНМЕСЯЦА(B4;0);
КОНМЕСЯЦА(B4;0)-(ДЕНЬНЕД(КОНМЕСЯЦА(B4;0);2)-5));
0; Праздники!$A$2:$A$827)
=WORKDAY(
IF(WEEKDAY(EOMONTH(B4,0),2)<6, EOMONTH(B4,0),
EOMONTH(B4,0)-(WEEKDAY(EOMONTH(B4,0),2)-5)),
0,Праздники!$A$2:$A$827)
где Праздники!$A$2:$A$827 — ссылка на диапазон дат с праздниками
Здесь я так же использую КОНМЕСЯЦА для быстрого определения последней даты месяца.
Функция ДЕНЬНЕД(WEEKDAY) возвращает номер дня недели для указанной даты и нужна для того, чтобы определить — является последний день недели субботой или воскресеньем. Если нет, то возвращаем дату как есть, если это суббота или воскресенье — то отнимаем от даты либо 1 день, либо 2(если это СБ — то 1, если ВСК — то 2).
И только после этого применяем к полученной дате функцию РАБДЕНЬ(WORKDAY), которая для последней даты месяца определяет, является ли она праздничной(на основании списка праздников Праздники!$A$2:$A$827). Если дата праздничная — то она уменьшается до тех пор, пока не достигнет рабочего дня. РАБДЕНЬ не принимает в расчет выходные, поэтому нам и нужны функции ЕСЛИ и ДЕНЬНЕД, прежде чем применить РАБДЕНЬ.

Однако сразу хочу оговорить, что в конкретно моем случае вычисление выходных дней при помощи ЕСЛИ и ДЕНЬНЕД несколько избыточно, т.к. в диапазоне с праздниками помимо непосредственно праздников у меня уже учтены все выходные дни. Т.е. по сути формула могла бы быть намного проще:
=РАБДЕНЬ(КОНМЕСЯЦА(B4;0); 0; Праздники!$A$2:$A$827)
=WORKDAY(EOMONTH(B4,0), 0, Праздники!$A$2:$A$827)
Но я все равно решил именно в статье привести формулу, которая смотрит и на дни недели, т.к. требования могут быть разными.

Т.к. Microsoft все же немного заботится о нас, то для пользователей версий Excel 2010 и более новых, в случае необходимости учитывать день недели прямо в формуле, можно использовать функцию РАБДЕНЬ.МЕЖД:
=РАБДЕНЬ.МЕЖД(КОНМЕСЯЦА(B4;0);0;1;Праздники!$A$2:$A$827)
=WORKDAY.INTL(EOMONTH(B4,0),0,1,Праздники!$A$2:$A$827)
РАБДЕНЬ.МЕЖД[дата; кол-во дней; выходные; праздники]
дата — дата, от которой необходимо отсчитать указанное кол-во дней
кол-во дней — количество дней, которые надо прибавить или отнять(отриц. число — отнимает дни от даты) от указанной даты
выходные — 1 = Суббота и Воскресенье, 2 — Воскресенье и Понедельник и т.д. Полный перечень есть в справке для функции и в выпадающей подсказке к функции при вводе.
праздники — ссылка на диапазон дат с праздниками
Достаточно указать последнюю дату месяца, указать для неё сдвиг на 0 дней, указать тип выходных и ссылку на диапазон дат с праздниками. Все уже сделано и все гораздо проще.


Последний рабочий день при помощи функции пользователя на VBA

Если использование VBA не является для вас проблемой, то можно применить функцию пользователя(UDF) для расчета последнего рабочего дня:

'---------------------------------------------------------------------------------------
' Author : The_Prist(Щербаков Дмитрий)
'          Профессиональная разработка приложений для MS Office любой сложности
'          Проведение тренингов по MS Excel
'          http://www.excel-vba.ru
'          WebMoney - R298726502453; Яндекс.Деньги - 41001332272872
' Purpose: Функция получения последнего рабочего дня на основании указанной даты и списка праздников
'---------------------------------------------------------------------------------------
Option Explicit
 
Function ПоследнийРабочийДень(Дата As Date, Optional Праздники As Range = Nothing, Optional СистемныеВыходные As Boolean = False)
    Dim dd As Date, dres As Date
    Dim lWeekDay As Long
 
    dres = DateSerial(Year(Дата), Month(Дата) + 1, 0)
    If СистемныеВыходные Then
        lWeekDay = Weekday(dres, vbUseSystemDayOfWeek)
        If lWeekDay < 6 Then
            dres = dres
        Else
            dres = dres - (lWeekDay - 5)
        End If
    End If
    Do While (IsHoliday(dres, Праздники))
        dres = dres - 1
    Loop
    ПоследнийРабочийДень = dres
End Function
 
'Функция поиска указанной даты среди праздничных дат
'       dd          - искомая дата
'       Holidays    - диапазон с праздничными днями
Function IsHoliday(ByVal dd As Date, Optional Holidays As Range = Nothing)
    Dim lWeekDay As Long
    Dim x, rr As Range
 
    If Holidays Is Nothing Then Exit Function
    For Each x In Holidays.Value
        If IsDate(x) Then
            If CDate(x) = dd Then
                IsHoliday = True
                Exit Function
            End If
        End If
    Next
End Function

Чтобы правильно использовать приведенный код, необходимо сначала ознакомиться со статьей Что такое функция пользователя(UDF)?. Вкратце: скопировать текст кода выше, перейти в редактор VBA(Alt+F11) -создать стандартный модуль(InsertModule) и в него вставить скопированный текст. После чего функцию можно будет вызвать из Диспетчера функций(Ctrl+F3), отыскав её в категории Определенные пользователем (User Defined Functions).
Синтаксис функции:
=ПоследнийРабочийДень(B4;Праздники!$A$2:$A$827;0)

  • Дата(B4) — непосредственно дата или ссылка на ячейку с датой, последней рабочий день для которой необходимо вычислить. Будет рассчитан последний рабочий день для месяца указанной даты.
  • Праздники() — ссылка на диапазон ячеек, содержащих даты праздничных дней.
  • СистемныеВыходные(0) — ИСТИНА(TRUE или 1) или ЛОЖЬ(FALSE или 0). Если указано как ЛОЖЬ, то при вычислении последнего рабочего дня не будут учитываться выходные. В этом случае они обязательно должны быть перечислены в списке Праздники. Если они не перечислены — то все дни недели считаются рабочими, кроме праздников. Если указано как ИСТИНА, то в качестве выходных будут применены те дни, которые установлены для календаря в операционной системе. Для русской локализации это как правило Суббота и Воскресенье.

Последний рабочий день при помощи PowerQuery

Самый экзотический метод. Если еще не знаете что такое PowerQuery — Power Query — что такое и почему её необходимо использовать в работе?.
Для начала необходимо загрузить список праздников.

Если список праздников еще не преобразован в умную таблицу, то на листе Праздники выделяем все ячейки с датами -переходим на вкладку Вставка(Insert)Таблица(Table). Снимаем галку с пункта «Таблица с заголовками» —Ок:
Создание умной таблицы

Выделяем любую ячейку в созданной таблице праздников -переходим на вкладку Данные(Data или Power Query) и выбираем Из таблицы(From Table).
Нажимаем в заголовке на значок календаря и в выпадающем списке выбираем тип Дата:
Изменить тип на Дата
В правой части окна редактора изменяем название запроса(скорее всего там Таблица1) на Праздники:
Переименование запроса
Переходим на вкладку Главная, раскрываем пункт Закрыть и загрузить и выбираем Закрыть и загрузить в…:
Загрузить
В появившемся окне выбираем Только создать подключение и нажимаем Ок:
Создать подключение
Теперь переходим на вкладку Данные(Data) -Получить данные -Из других источников -Пустой запрос. Переходим в расширенный редактор(вкладка ГлавнаяРасширенный редактор):
Расширенный редактор
и вставляем туда следующий текст:

let
dNow = Date.From(DateTime.LocalNow()),
//dNow = Date.FromText(«2017-09-19»),
lastDay = Date.EndOfMonth(dNow),
WeekD = Date.DayOfWeek(lastDay,1),
dd = if WeekD < 5 then lastDay else Date.AddDays(lastDay,-(WeekD-4)),
//dd = dNow,
coun_dif = (value as date) as date =>
let
dAdd = value,
select_rows = Table.SelectRows(Праздники, each Record.Field(_, «Дата выходного дня») = dAdd),
count_rows = Table.RowCount(select_rows),
result = Date.AddDays(value,-count_rows)
in
result,
res_d = Table.FromValue(coun_dif(dd))
in
res_d

После этого можно на вкладке Главная нажать Закрыть и загрузить. Будет создан новый лист с одной ячейкой — датой последнего рабочего дня.
Чтобы приведенный запрос работал корректно, необходимо назвать столбец с праздничными датами «Дата выходного дня». Либо изменить это название в самом запросе.
Если нужен последний рабочий день на конкретную дату, то необходимо убрать первую строку(dNow = Date.From(DateTime.LocalNow()),) и убрать слеши вначале следующей строки:
let
dNow = Date.FromText(«2017-09-19»),
lastDay = Date.EndOfMonth(dNow),
WeekD = Date.DayOfWeek(lastDay,1),
dd = if WeekD < 5 then lastDay else Date.AddDays(lastDay,-(WeekD-4)),
//dd = Date.EndOfMonth(dNow),
coun_dif = (value as date) as date =>
let
dAdd = value,
select_rows = Table.SelectRows(Праздники, each Record.Field(_, «Дата выходного дня») = dAdd),
count_rows = Table.RowCount(select_rows),
result = Date.AddDays(value,-count_rows)
in
result,
res_d = Table.FromValue(coun_dif(dd))
in
res_d
Если выходные не надо учитывать(чтобы суббота и воскресенье не рассчитывались автоматом в зависимости от дня недели), то запрос будет выглядеть так:
let
dNow = Date.FromText(«2017-09-19»),
dd = Date.EndOfMonth(dNow),
coun_dif = (value as date) as date =>
let
dAdd = value,
select_rows = Table.SelectRows(Праздники, each Record.Field(_, «Дата выходного дня») = dAdd),
count_rows = Table.RowCount(select_rows),
result = Date.AddDays(value,-count_rows)
in
result,
res_d = Table.FromValue(coun_dif(dd))
in
res_d

Реализацию всех приведенных решений можно скачать в приложенном файле
Скачать файл:

  ПоследнийРабочийДень.xlsm (50,7 KiB, 617 скачиваний)


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам



Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

Date yes Add (Subtract) Days to a Date Concatenate Dates Convert Date to Number Convert Date to Text Month Name to Number Create Date Range from Dates Day Number of Year Month Name from Date First Day of Month Add (Subtract) Weeks to a Date If Functions with Dates Max Date Number of Days Between Dates Number of Days in a Month Number of Weeks Between Dates Number of Years Between Dates Split Date & Time into Separate Cells Countdown Remaining Days Insert Dates Random Date Generator Using Dynamic Ranges — Year to Date Values Add (Subtract) Years to a Date Date Formula Examples Extract Day from Date Get Day Name from Date Count Days Left in Month / Year Count Workdays Left in Month / Year Get Last Day of Month Last Business Day of Month / Year Number of Work / Business Days in Month Weekday Abbreviations Auto Populate Dates Number of Months Between Dates Quarter from a Date Years of Service Change Date Format Compare Dates Time yes Add (Subtract) Hours to Time Add (Subtract) Minutes to Time Add (Subtract) Seconds to Time Add Up time (Total Time) Time Differences Change Time Format Convert Minutes to Hours Convert Time to Decimal Convert Time to Hours Convert Time to Minutes Convert Time to Seconds Military Time Round Time to Nearest 15 Minutes Overtime Calculator Number of Hours Between Times Convert Seconds to Minutes, Hours, or Time Count Hours Worked Time Differences Time Format — Show Minutes Seconds Text yes Add Commas to Cells Get First Word from Text Capitalize First Letter Clean & Format Phone #s Remove Extra Trailing / Leading Spaces Add Spaces to Cell Assign Number Value to Text Combine Cells with Comma Combine First and Last Names Convert Text String to Date Convert Text to Number Extract Text From Cell Get Last Word Remove Unwated Characters Extract Text Before or After Character How to Split Text String by Space, Comma, & More Remove Special Characters Remove First Characters from Left Substitute Multiple Values Switch First & Last Names w/ Commas Remove Specific Text from a Cell Extract Text Between Characters (Ex. Parenthesis) Add Leading Zeros to a Number Remove Line Breaks from Text Remove all Numbers from Text Reverse Text Remove Non-Numeric Characters Remove Last Character(s) From Right Separate First and Last Names Separate Text & Numbers Round yes Round Formulas Round Price to Nearest Dollar or Cent Round to Nearest 10, 100, or 1000 Round to Nearest 5 or .5 Round Percentages Round to Significant Figures Count yes Count Blank and Non-blank Cells Count Cells Between Two Numbers Count Cells not Equal to Count if Cells are in Range Count Times Word Appears in Cell Count Words in Cell Count Specific Characters in Column Count Total Number of Characters in Column Count Cells that Equal one of two Results Count Cells that do not Contain Count Cells that Contain Specific Text Count Unique Values in Range Countif — Multiple Criteria Count Total Number of Cells in Range Count Cells with Any Text Count Total Cells in a Table Lookup yes Two Dimensional VLOOKUP VLOOKUP Simple Example Vlookup — Multiple Matches Case Sensitive Lookup Case Sensitive VLOOKUP Sum if — VLOOKUP Case Sensitive Lookup Case Sensitive VLOOKUP Find Duplicates w/ VLOOKUP or MATCH INDEX MATCH MATCH Lookup — Return Cell Address (Not Value) Lookup Last Value in Column or Row Reverse VLOOKUP (Right to Left) Risk Score Bucket with VLOOKUP Sum with a VLOOKUP Function VLOOKUP & INDIRECT VLOOKUP Concatenate VLOOKUP Contains (Partial Match) 17 Reasons Why Your XLOOKUP is Not Working Double (Nested) XLOOKUP — Dynamic Columns IFERROR (& IFNA) XLOOKUP Lookup Min / Max Value Nested VLOOKUP Top 11 Alternatives to VLOOKUP (Updated 2022!) VLOOKUP – Dynamic Column Reference VLOOKUP – Fix #N/A Error VLOOKUP – Multiple Sheets at Once VLOOKUP & HLOOKUP Combined VLOOKUP & MATCH Combined VLOOKUP Between Worksheets or Spreadsheets VLOOKUP Duplicate Values VLOOKUP Letter Grades VLOOKUP Return Multiple Columns VLOOKUP Returns 0? Return Blank Instead VLOOKUP w/o #N/A Error XLOOKUP Multiple Sheets at Once XLOOKUP Between Worksheets or Spreadsheets XLOOKUP by Date XLOOKUP Duplicate Values XLOOKUP Multiple Criteria XLOOKUP Return Multiple Columns XLOOKUP Returns 0? Return Blank Instead XLOOKUP Text XLOOKUP with IF XLOOKUP With If Statement Misc. yes Sort Multiple Columns Use Cell Value in Formula Percentage Change Between Numbers Percentage Breakdown Rank Values Add Spaces to Cell CAGR Formula Average Time Decimal Part of Number Integer Part of a Number Compare Items in a List Dealing with NA() Errors Get Worksheet Name Wildcard Characters Hyperlink to Current Folder Compound Interest Formula Percentage Increase Create Random Groups Sort with the Small and Large Functions Non-volatile Function Alternatives Decrease a Number by a Percentage Calculate Percent Variance Profit Margin Calculator Convert Column Number to Letter Get Full Address of Named Range Insert File Name Insert Path Latitute / Longitude Functions Replace Negative Values Reverse List Range Convert State Name to Abbreviation Create Dynamic Hyperlinks Custom Sort List with Formula Data Validation — Custom Formulas Dynamic Sheet Reference (INDIRECT) Reference Cell in Another Sheet or Workbook Get Cell Value by Address Get Worksheet Name Increment Cell Reference List Sheet Names List Skipped Numbers in Sequence Return Address of Max Value in Range Search by Keywords Select Every Other (or Every nth) Row Basics yes Cell Reference Basics — A1, R1C1, 3d, etc. Add Up (Sum) Entire Column or Row Into to Dynamic Array Formulas Conversions yes Convert Time Zones Convert Celsius to Fahrenheit Convert Pounds to Kilograms Convert Time to Unix Time Convert Feet to Meters Convert Centimeters to Inches Convert Kilometers to Miles Convert Inches to Feet Convert Date to Julian Format Convert Column Letter to Number Tests yes Test if a Range Contains any Text Test if any Cell in Range is Number Test if a Cell Contains a Specific Value Test if Cell Contains Any Number Test if Cell Contains Specific Number Test if Cell is Number or Text If yes Percentile If Subtotal If Sumproduct If Large If and Small If Median If Concatentate If Max If Rank If TEXTJOIN If Sum yes Sum if — Begins With / Ends With Sum if — Month or Year to Date Sum if — By Year Sum if — Blank / Non-Blank Sum if — Horizontal Sum Count / Sum If — Cell Color INDIRECT Sum Sum If — Across Multiple Sheets Sum If — By Month Sum If — Cells Not Equal To Sum If — Not Blank Sum if — Between Values Sum If — Week Number Sum Text Sum if — By Category or Group Sum if — Cell Contains Specific Text (Wildcards) Sum if — Date Rnage Sum if — Dates Equal Sum if — Day of Week Sum if — Greater Than Sum if — Less Than Average yes Average Non-Zero Values Average If — Not Blank Average — Ignore 0 Average — Ignore Errors Math yes Multiplication Table Cube Roots nth Roots Square Numbers Square Roots Calculations yes Calculate a Ratio Calculate Age KILLLLLLL Calculate Loan Payments GPA Formula Calculate VAT Tax How to Grade Formulas Find yes Find a Number in a Column / Workbook Find Most Frequent Numbers Find Smallest n Values Find nth Occurance of Character in Text Find and Extract Number from String Find Earliest or Latest Date Based on Criteria Find First Cell with Any Value Find Last Row Find Last Row with Data Find Missing Values Find Largest n Values Most Frequent Number Conditional Formatting yes Conditional Format — Dates & Times Conditional Format — Highlight Blank Cells New Functions XLOOKUP Replaces VLOOKUP, HLOOKUP, and INDEX / MATCH Logical yes AND Checks whether all conditions are met. TRUE/FALSE IF If condition is met, do something, if not, do something else. IFERROR If result is an error then do something else. NOT Changes TRUE to FALSE and FALSE to TRUE. OR Checks whether any conditions are met. TRUE/FALSE XOR Checks whether one and only one condition is met. TRUE/FALSE Lookup & Reference yes FALSE The logical value: FALSE. TRUE The logical value: TRUE. ADDRESS Returns a cell address as text. AREAS Returns the number of areas in a reference. CHOOSE Chooses a value from a list based on it’s position number. COLUMN Returns the column number of a cell reference. COLUMNS Returns the number of columns in an array. HLOOKUP Lookup a value in the first row and return a value. HYPERLINK Creates a clickable link. INDEX Returns a value based on it’s column and row numbers. INDIRECT Creates a cell reference from text. LOOKUP Looks up values either horizontally or vertically. MATCH Searches for a value in a list and returns its position. OFFSET Creates a reference offset from a starting point. ROW Returns the row number of a cell reference. ROWS Returns the number of rows in an array. TRANSPOSE Flips the oriention of a range of cells. VLOOKUP Lookup a value in the first column and return a value. Date & Time yes DATE Returns a date from year, month, and day. DATEDIF Number of days, months or years between two dates. DATEVALUE Converts a date stored as text into a valid date DAY Returns the day as a number (1-31). DAYS Returns the number of days between two dates. DAYS360 Returns days between 2 dates in a 360 day year. EDATE Returns a date, n months away from a start date. EOMONTH Returns the last day of the month, n months away date. HOUR Returns the hour as a number (0-23). MINUTE Returns the minute as a number (0-59). MONTH Returns the month as a number (1-12). NETWORKDAYS Number of working days between 2 dates. NETWORKDAYS.INTL Working days between 2 dates, custom weekends. NOW Returns the current date and time. SECOND Returns the second as a number (0-59) TIME Returns the time from a hour, minute, and second. TIMEVALUE Converts a time stored as text into a valid time. TODAY Returns the current date. WEEKDAY Returns the day of the week as a number (1-7). WEEKNUM Returns the week number in a year (1-52). WORKDAY The date n working days from a date. WORKDAY.INTL The date n working days from a date, custom weekends. YEAR Returns the year. YEARFRAC Returns the fraction of a year between 2 dates. Engineering yes CONVERT Convert number from one unit to another. Financial yes FV Calculates the future value. PV Calculates the present value. NPER Calculates the total number of payment periods. PMT Calculates the payment amount. RATE Calculates the interest Rate. NPV Calculates the net present value. IRR The internal rate of return for a set of periodic CFs. XIRR The internal rate of return for a set of non-periodic CFs. PRICE Calculates the price of a bond. YIELD Calculates the bond yield. INTRATE The interest rate of a fully invested security. Information yes CELL Returns information about a cell. ERROR.TYPE Returns a value representing the cell error. ISBLANK Test if cell is blank. TRUE/FALSE ISERR Test if cell value is an error, ignores #N/A. TRUE/FALSE ISERROR Test if cell value is an error. TRUE/FALSE ISEVEN Test if cell value is even. TRUE/FALSE ISFORMULA Test if cell is a formula. TRUE/FALSE ISLOGICAL Test if cell is logical (TRUE or FALSE). TRUE/FALSE ISNA Test if cell value is #N/A. TRUE/FALSE ISNONTEXT Test if cell is not text (blank cells are not text). TRUE/FALSE ISNUMBER Test if cell is a number. TRUE/FALSE ISODD Test if cell value is odd. TRUE/FALSE ISREF Test if cell value is a reference. TRUE/FALSE ISTEXT Test if cell is text. TRUE/FALSE N Converts a value to a number. NA Returns the error: #N/A. TYPE Returns the type of value in a cell. Math yes ABS Calculates the absolute value of a number. AGGREGATE Define and perform calculations for a database or a list. CEILING Rounds a number up, to the nearest specified multiple. COS Returns the cosine of an angle. DEGREES Converts radians to degrees. DSUM Sums database records that meet certain criteria. EVEN Rounds to the nearest even integer. EXP Calculates the exponential value for a given number. FACT Returns the factorial. FLOOR Rounds a number down, to the nearest specified multiple. GCD Returns the greatest common divisor. INT Rounds a number down to the nearest integer. LCM Returns the least common multiple. LN Returns the natural logarithm of a number. LOG Returns the logarithm of a number to a specified base. LOG10 Returns the base-10 logarithm of a number. MOD Returns the remainder after dividing. MROUND Rounds a number to a specified multiple. ODD Rounds to the nearest odd integer. PI The value of PI. POWER Calculates a number raised to a power. PRODUCT Multiplies an array of numbers. QUOTIENT Returns the integer result of division. RADIANS Converts an angle into radians. RAND Calculates a random number between 0 and 1. RANDBETWEEN Calculates a random number between two numbers. ROUND Rounds a number to a specified number of digits. ROUNDDOWN Rounds a number down (towards zero). ROUNDUP Rounds a number up (away from zero). SIGN Returns the sign of a number. SIN Returns the sine of an angle. SQRT Calculates the square root of a number. SUBTOTAL Returns a summary statistic for a series of data. SUM Adds numbers together. SUMIF Sums numbers that meet a criteria. SUMIFS Sums numbers that meet multiple criteria. SUMPRODUCT Multiplies arrays of numbers and sums the resultant array. TAN Returns the tangent of an angle. TRUNC Truncates a number to a specific number of digits. Stats yes AVERAGE Averages numbers. AVERAGEA Averages numbers. Includes text & FALSE =0, TRUE =1. AVERAGEIF Averages numbers that meet a criteria. AVERAGEIFS Averages numbers that meet multiple criteria. CORREL Calculates the correlation of two series. COUNT Counts cells that contain a number. COUNTA Count cells that are non-blank. COUNTBLANK Counts cells that are blank. COUNTIF Counts cells that meet a criteria. COUNTIFS Counts cells that meet multiple criteria. FORECAST Predict future y-values from linear trend line. FREQUENCY Counts values that fall within specified ranges. GROWTH Calculates Y values based on exponential growth. INTERCEPT Calculates the Y intercept for a best-fit line. LARGE Returns the kth largest value. LINEST Returns statistics about a trendline. MAX Returns the largest number. MEDIAN Returns the median number. MIN Returns the smallest number. MODE Returns the most common number. PERCENTILE Returns the kth percentile. PERCENTILE.INC Returns the kth percentile. Where k is inclusive. PERCENTILE.EXC Returns the kth percentile. Where k is exclusive. QUARTILE Returns the specified quartile value. QUARTILE.INC Returns the specified quartile value. Inclusive. QUARTILE.EXC Returns the specified quartile value. Exclusive. RANK Rank of a number within a series. RANK.AVG Rank of a number within a series. Averages. RANK.EQ Rank of a number within a series. Top Rank. SLOPE Calculates the slope from linear regression. SMALL Returns the kth smallest value. STDEV Calculates the standard deviation. STDEV.P Calculates the SD of an entire population. STDEV.S Calculates the SD of a sample. STDEVP Calculates the SD of an entire population TREND Calculates Y values based on a trendline. Text yes CHAR Returns a character specified by a code. CLEAN Removes all non-printable characters. CODE Returns the numeric code for a character. CONCATENATE Combines text together. DOLLAR Converts a number to text in currency format. EXACT Test if cells are exactly equal. Case-sensitive. TRUE/FALSE FIND Locates position of text within a cell.Case-sensitive. LEFT Truncates text a number of characters from the left. LEN Counts number of characters in text. LOWER Converts text to lower case. MID Extracts text from the middle of a cell. PROPER Converts text to proper case. REPLACE Replaces text based on it’s location. REPT Repeats text a number of times. RIGHT Truncates text a number of characters from the right. SEARCH Locates position of text within a cell.Not Case-sensitive. SUBSTITUTE Finds and replaces text. Case-sensitive. TEXT Converts a value into text with a specific number format. TRIM Removes all extra spaces from text. UPPER Converts text to upper case. VALUE Converts a number stored as text into a number.

0 / 0 / 0

Регистрация: 15.08.2018

Сообщений: 30

1

Excel

Нужно определить количество определенных рабочих дней недели и или их комбинаций в интервале дат

15.08.2018, 11:14. Показов 6996. Ответов 43


Студворк — интернет-сервис помощи студентам

Здравствуйте!

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



0



Loya

70 / 57 / 24

Регистрация: 06.12.2015

Сообщений: 300

15.08.2018, 15:04

2

А где в файле код?

Посчитать рабочие дни можно так (предполагаем, что как в приложенном файле начало периода указано в ячейкеА1, конец периода в ячейке А2, перечисление праздничных дней начинается с ячейки А7):

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Private Sub main()
 
Dim Date1, Date2 As Date
Date1 = CDate(Cells(1, 1))
Date2 = CDate(Cells(2, 1))
MsgBox ("Рабочих дней " & workDays(Date1, Date2, 7))
 
End Sub
 
Private Function workDays(ByVal bDate As Date, ByVal eDate As Date, startWeekends As Long) As Integer
 
Dim wDays As Integer
Dim lastRow As Long
 
For d = bDate To eDate
    itsday = Weekday(d, vbMonday)
    If itsday <> 6 Or itsday <> 7 Then
        wDays = wDays + 1
    End If
Next d
 
lastRow = Cells(Rows.Count, 1).End(xlUp).Row 'получаем последнюю заполненную ячейку
weekends = lastRow - startWeekends + 1 'вычисляем количество праздничных дней
wDays = wDays - weekends
 
workDays = wDays
 
End Function

Про комбинации рабочих дней не совсем понятно, по одному дню это тоже комбинация? Должно быть:
понедельник
вторник

понедельник, вторник, среда

понедельник, вторник, среда, четверг, пятница
???



0



0 / 0 / 0

Регистрация: 15.08.2018

Сообщений: 30

15.08.2018, 16:20

 [ТС]

3

Loya, спасибо огромное, за ответ!

Сейчас попробую понятнее объяснить что именно нужно:
есть интервал дат (на пример): 15.08.2018 — 23.08.2018. В него входят:2 среды, 2 четверга, 1 пятница, 1 сб, 1 вс, 1 пн и 1 вт.
Нужно заставить выяснить это Exel, потом что-бы он проверил не приходятся ли эти дни на праздники и сложил их.



0



70 / 57 / 24

Регистрация: 06.12.2015

Сообщений: 300

15.08.2018, 17:16

4

Т.е. вывод по заданным датам (15.08.2018 — 23.08.2018) должен быть:
среда — 2шт.
четверг — 2шт.
пятница — 1шт.
суббота — 1шт.
воскресенье — 1шт.
понедельник — 1шт.
вторник — 1шт.
Всего рабочих дней: 7шт.

А, например, за период 3.05.2018-14.05.2018 вывод должен быть такой:
четверг — 2шт.
пятница — 2шт.
суббота — 2шт.
воскресенье — 2шт.
понедельник — 2шт.
вторник — 1шт.
среда — 1шт.
Всего рабочих дней: 9шт.
(т.к. 12 дней — 4 выходных и — 1 праздник)

Так что-ли?



0



Burk

1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

16.08.2018, 08:42

5

PiLLyulk, такой вариант

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Function DayW(D1 As Date, D2 As Date)
Dim I As Integer, S As Integer, S1 As Integer, Wd As Integer
S = 0
'количество дней недели в заданном интервале
'начало недели - воскресенье
For I = 1 To 7
  Cells(I, 1) = (D2 - I)  7 - (D1 - I - 1)  7
  If I > 1 And I < 7 Then S = S + Cells(I, 1)
Next
I = 10
'начиная с десятой строки в первом столбце располагаются даты праздников
Do While Cells(I, 1) <> ""
  Wd = Weekday(Cells(I, 1))
  If Wd > 1 And Wd < 7 And Cells(I, 1) >= D1 And Cells(I, 1) <= D2 Then S = S - 1
  I = I + 1
Loop
DayW = S
End Function
 
Sub proba()
Dim D1 As Date, D2 As Date
D1 = CDate("09.08.2018")
D2 = CDate("25.08.2018")
MsgBox DayW(D1, D2)
End Sub

Добавлено через 8 минут
PiLLyulk, во втором столбце с первой по седьмую строку можно ввести дни недели воскресенье — суббота



0



0 / 0 / 0

Регистрация: 15.08.2018

Сообщений: 30

16.08.2018, 10:20

 [ТС]

6

Loya, добрый день.

Цитата
Сообщение от Loya
Посмотреть сообщение

Т.е. вывод по заданным датам (15.08.2018 — 23.08.2018) должен быть:
среда — 2шт.
четверг — 2шт.
пятница — 1шт.
суббота — 1шт.
воскресенье — 1шт.
понедельник — 1шт.
вторник — 1шт.
Всего рабочих дней: 7шт.
А, например, за период 3.05.2018-14.05.2018 вывод должен быть такой:
четверг — 2шт.
пятница — 2шт.
суббота — 2шт.
воскресенье — 2шт.
понедельник — 2шт.
вторник — 1шт.
среда — 1шт.
Всего рабочих дней: 9шт.
(т.к. 12 дней — 4 выходных и — 1 праздник)
Так что-ли?

Да, я думаю, что как-то так это должно быть. Тут самое главное что-бы можно было выбрать конкретные дни недели.
Например (нужны вторники и четверги):
за период 3.05.2018-14.05.2018 вывод должен быть такой:
четверг — 2шт. 1 четверг — это День победы, он не должен попасть в результат.
пятница — 2шт.
суббота — 2шт.
воскресенье — 2шт.
понедельник — 2шт.
вторник — 1шт.
среда — 1шт.
Всего 1 вторник и 2 четверга, 1 из этих дней праздничный, значит всего 2 штуки.

Добавлено через 29 минут
Burk, если четно, я не понял как эта штука работает. Не смог ее выполнить. Я пока очень плохо в этом разбираюсь.

Вот эта часть вообще не понял что делать должна:

Цитата
Сообщение от Burk
Посмотреть сообщение

Do While Cells(I, 1) <> «»
* Wd = Weekday(Cells(I, 1))
* If Wd > 1 And Wd < 7 And Cells(I, 1) >= D1 And Cells(I, 1) <= D2 Then S = S — 1
* I = I + 1
Loop



0



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

16.08.2018, 12:04

7

Цитата
Сообщение от PiLLyulk
Посмотреть сообщение

Вот эта часть вообще не понял что делать должна

Да, тяжелый случай, эта часть вычитает из рабочих дней праздники заданного промежутка.
Для того, чтобы посмотреть всё надо запустить макрос, он здесь единственный proba. Промежуток заданный в моём примере, D1 = и D2 = в этом макросе. Запустить макрос из вкладки Разработчик — Макросы — proba. Или спросите у друзей, которые продвинулись в экселе дальше, чем вы (если такие есть)

Добавлено через 7 минут
В тексте функции тоже есть пояснения. Ещё раз — с ячейки А10 вниз введите даты праздников



0



0 / 0 / 0

Регистрация: 15.08.2018

Сообщений: 30

16.08.2018, 12:15

 [ТС]

8

Цитата
Сообщение от Burk
Посмотреть сообщение

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

Вроде понял теперь, она перебирает даты, начиная с 10 строки, и если они попадают в заданный интервал, то вычитает их количество.
Если взять интервал с 1.05.2019 по 15.05.2019, то Проба выдает 9 дней. Там их всего 15, из них 4 выходных и 1 праздничный день. Не понимаю что она имеет ввиду.
Это какие-то условия по дням недели?

Цитата
Сообщение от Burk
Посмотреть сообщение

For I = 1 To 7
* Cells(I, 1) = (D2 — I) 7 — (D1 — I — 1) 7
* If I > 1 And I < 7 Then S = S + Cells(I, 1)

Спасибо, что возитесь со мной.



0



Loya

70 / 57 / 24

Регистрация: 06.12.2015

Сообщений: 300

16.08.2018, 13:21

9

Цитата
Сообщение от PiLLyulk
Посмотреть сообщение

Там их всего 15, из них 4 выходных и 1 праздничный день. Не понимаю что она имеет ввиду.
Это какие-то условия по дням недели?

Праздничных два (1.05.2019 и 9.05.2019).

Цитата
Сообщение от PiLLyulk
Посмотреть сообщение

Да, я думаю, что как-то так это должно быть. Тут самое главное что-бы можно было выбрать конкретные дни недели.
Например (нужны вторники и четверги):

Цитата
Сообщение от PiLLyulk
Посмотреть сообщение

Всего 1 вторник и 2 четверга, 1 из этих дней праздничный, значит всего 2 штуки.

Вот тут непонятно, нужно праздничный учитывать как вторник или нет? Если нужно то вот так примерно:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Private Sub main()
 
Dim bDate As Date, eDate As Date 'переменные для периода
Dim startWeekend As Long 'строка, с которой начинаются праздники
Dim workDays As Integer 'переменная для количества рабочих дней
Dim lastRow As Long 'переменная для последней заполненной ячейки праздников
Dim arrWorkDays(1 To 7) As Integer 'массив для дней недели
Dim str As String, days() As String 'переменные для запрашиваемых дней
Dim flagWeekday As Boolean 'флаг
 
bDate = CDate(Cells(1, 1))
eDate = CDate(Cells(2, 1))
startWeekend = 7
 
lastRow = Cells(Rows.Count, 1).End(xlUp).Row 'получаем последнюю заполненную ячейку
For d = bDate To eDate 'цикл по датам в периоде
    itsday = Weekday(d, vbMonday) 'определяем день недели
    arrWorkDays(itsday) = arrWorkDays(itsday) + 1 'увеличиваем в массиве тот разряд, к которому относится день недели
    If itsday <> 6 And itsday <> 7 Then 'если это не суббота и не воскресенье
        flagWeekday = False 'сбрасываем флаг
        For j = startWeekend To lastRow 'пробегаемся по праздникам
            If Cells(j, 1) = d Then 'если есть в списке праздников
                flagWeekday = True 'устанавливаем флаг
            End If
        Next j
        If Not flagWeekday Then 'если флаг не установлен
            workDays = workDays + 1 'то увеличиваем счётчик рабочих дней
        End If
    End If
Next d
 
str = InputBox("Введите через запятую номера дней недели от 1 до 7", "Ввод данных")
days = Split(str, ",") 'разделяем полученные дни по запятым
 
For i = 0 To UBound(days) 'перебираем циклом запрошенные дни 
    Call showResult(days(i), arrWorkDays(i + 1)) 'вызываем функцию, которая покажет день недели и количество этих дней
Next i
MsgBox ("Общее количество рабочих дней " & workDays)
End Sub
 
Private Sub showResult(ByVal dName As String, ByVal result As Integer)
    If IsNumeric(dName) Then
        If CInt(dName) > -1 And CInt(dName) < 8 Then
            MsgBox (WeekdayName(CLng(dName)) & " " & result) 'показываем день недели и количество этих дней в периоде
        Else
            MsgBox ("Значение не является днём недели!")
        End If
    Else
        MsgBox ("Значение не является числом!")
    End If
End Sub

Если праздничный не нужно учитывать, как день недели, то подправьте условие.

Цитата
Сообщение от Burk
Посмотреть сообщение

Да, тяжелый случай

Уважаю Вас и Ваше желание помочь, но зачем же так грубо? Все когда-то начинали. Разбирать чужой код даже опытному порой бывает сложно, а начинающему это сложно втройне.

Добавлено через 3 минуты

Цитата
Сообщение от PiLLyulk
Посмотреть сообщение

Спасибо, что возитесь со мной.

Можно жмакать кнопку «Спасибо» по сообщением, тогда у тех, кто «возится» будет расти репутация!



0



0 / 0 / 0

Регистрация: 15.08.2018

Сообщений: 30

16.08.2018, 14:19

 [ТС]

10

Loya, спасибо! Это, практически то, что нужно.

Цитата
Сообщение от Loya
Посмотреть сообщение

Праздничных два (1.05.2019 и 9.05.2019).

Точно, я пор 1 мая забыл!

Цитата
Сообщение от Loya
Посмотреть сообщение

Вот тут непонятно, нужно праздничный учитывать как вторник или нет? Если нужно то вот так примерно:

Дни недели, попадающие на праздники не нужно учитывать. По итогу, если взять тот же пример: с 1 мая 2019 по 15 мая 2019 и выбрать вторник и четверг, то ответ должен получиться 3. (2 вторникa и 1 четверг, который не праздничный).

Получается, что нужно еще раз перебрать праздничные дни?



0



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

16.08.2018, 14:27

11

PiLLyulk, про случай я сказал по поводу того, что вы не знаете, что делать с присланным кодом.
Посылаю вам файл с вашим примером 2019 года, выдает на экран не 9, а 10, как и должно быть



0



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

16.08.2018, 14:33

12

PiLLyulk, в примере я поставил только один праздник 1 мая, если у вас в списке в А11 стоит и 9 иая, то должно быть 9



0



70 / 57 / 24

Регистрация: 06.12.2015

Сообщений: 300

16.08.2018, 15:10

13

Цитата
Сообщение от PiLLyulk
Посмотреть сообщение

Получается, что нужно еще раз перебрать праздничные дни?

Нет, зачем два раза? Лучше переписать придерживаясь необходимых условий. Просто непонятно, субботы и воскресенья нужно считать или нет? Мы их не считаем в количестве рабочих дней, а общее количество суббот и воскресений нужно? Если нужно, то опять вопрос, считаем ли субботу, если она выпадает на праздник (например, 5 января)? Т.е. нужно определиться с условием, для того, чтоб понять в какой момент перебирать праздничные дни, а в какой проверять день на «выходнойвость».



0



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

16.08.2018, 15:11

14

PiLLyulk, Cells(I, 1) = (D2 — I) 7 — (D1 — I — 1) 7 считает сколько I-ых дней недели в интервале дат
If I > 1 And I < 7 Then S = S + Cells(I, 1) суммирование рабочих дней (без воскресений (1) и суббот (7))



0



0 / 0 / 0

Регистрация: 15.08.2018

Сообщений: 30

16.08.2018, 15:48

 [ТС]

15

Цитата
Сообщение от Loya
Посмотреть сообщение

Нет, зачем два раза? Лучше переписать придерживаясь необходимых условий. Просто непонятно, субботы и воскресенья нужно считать или нет? Мы их не считаем в количестве рабочих дней, а общее количество суббот и воскресений нужно? Если нужно, то опять вопрос, считаем ли субботу, если она выпадает на праздник (например, 5 января)? Т.е. нужно определиться с условием, для того, чтоб понять в какой момент перебирать праздничные дни, а в какой проверять день на «выходнойвость».

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



0



Loya

70 / 57 / 24

Регистрация: 06.12.2015

Сообщений: 300

16.08.2018, 16:57

16

Лучший ответ Сообщение было отмечено PiLLyulk как решение

Решение

В таком случае сначала проверяем праздники, и если не праздничный, то записываем в массив, затем проверяем на выходнойство, если будни то увеличиваем ещё и счётчик рабочих дней. 5 января в этом случае в количество суббот не попадёт, что соответствует условию:

Цитата
Сообщение от PiLLyulk
Посмотреть сообщение

Тут смысл именно в том, что-бы посчитать сумму выбранных дней недели в определенном промежутке времени и что-бы туда праздники не попали.

Вот примерно так:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
Private Sub main()
 
Dim bDate As Date, eDate As Date
Dim startWeekend As Long
Dim workDays As Integer
Dim lastRow As Long
Dim arrWorkDays(1 To 7) As Integer
Dim str As String, days() As String
Dim flagWeekday As Boolean
 
bDate = CDate(Cells(1, 1))
eDate = CDate(Cells(2, 1))
startWeekend = 7
 
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
 
For d = bDate To eDate 
    itsday = Weekday(d, vbMonday) 'определяем день недели
    flagWeekday = False 'сбрасываем флаг
    For j = startWeekend To lastRow 'пробегаемся по праздникам
        If Cells(j, 1) = d Then
            flagWeekday = True 'если нашли, то устанавливаем флаг
            Exit For 'выходим из цикла т.к. нету смысла искать дальше
        End If
    Next j
    If Not flagWeekday Then
        arrWorkDays(itsday) = arrWorkDays(itsday) + 1 'добавляем в массив
        If itsday <> 6 And itsday <> 7 Then
            workDays = workDays + 1 'если это не выходной, то увеличиваем счётчик рабочих дней
        End If
    End If
Next d
 
str = InputBox("Введите через запятую номера дней недели от 1 до 7", "Ввод значений")
days = Split(str, ",")
 
For i = 0 To UBound(days)
    If IsNumeric(days(i)) Then
        If CInt(days(i)) > 0 And CInt(days(i)) < 8 Then
            MsgBox (WeekdayName(CLng(days(i))) & " " & arrWorkDays(days(i)))
        Else
            MsgBox ("Значение не является днём недели!")
        End If
        
    Else
        MsgBox ("Значение не является числом!")
    End If
Next i
MsgBox ("Общее количество рабочих дней " & workDays)
End Sub



1



0 / 0 / 0

Регистрация: 15.08.2018

Сообщений: 30

17.08.2018, 01:00

 [ТС]

17

Цитата
Сообщение от Loya
Посмотреть сообщение

Вот примерно так:

Спасибо! Это то, что нужно!

Добавлено через 53 минуты
Loya, здравствуйте.

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



0



Loya

70 / 57 / 24

Регистрация: 06.12.2015

Сообщений: 300

17.08.2018, 13:02

18

PiLLyulk, ну смотрите, вот тут:

Цитата
Сообщение от Loya
Посмотреть сообщение

bDate = CDate(Cells(1, 1))
eDate = CDate(Cells(2, 1))

Объявлены две переменные, которые как раз инициализируются данными из ячеек, преобразованными к типу Date. Т.е. если Вам нужно брать дни тоже из ячеек, то по аналогичному принципу и действуете. Измените вот эту строку:

Цитата
Сообщение от Loya
Посмотреть сообщение

str = InputBox(«Введите через запятую номера дней недели от 1 до 7», «Ввод значений»)

На:

Visual Basic
1
str = Cells(row, col)

где row — это будет номер строки, а col — номер колонки той ячейки, из которой необходимо получать данные.



0



PiLLyulk

0 / 0 / 0

Регистрация: 15.08.2018

Сообщений: 30

20.08.2018, 17:27

 [ТС]

19

Loya, добрый день.

А как убрать MsgBox, который выдает кол-во дней и сделать так что-бы сумма выбранных дней недели попадала в ячейку с функцией? Ну то-есть не понедельник: 2, среда: 2, кол-во рабочих:7, а просто 4 (среды+ понедельники)?

Добавлено через 7 часов 14 минут
Добрый день!

Пока получается такой вариант.

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Function Часы(bDate As Date, eDate As Date)
 
Dim startWeekend As Long
Dim workDays As Integer
Dim lastRow As Long
Dim arrWorkDays(1 To 7) As Integer
Dim str As String, days() As String
Dim flagWeekday As Boolean
 
 
startWeekend = 20
 
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
 
For d = bDate To eDate
    itsday = Weekday(d, vbMonday) 'определяем день недели
    flagWeekday = False 'сбрасываем флаг
    For j = startWeekend To lastRow 'пробегаемся по праздникам
        If Cells(j, 1) = d Then
            flagWeekday = True 'если нашли, то устанавливаем флаг
            Exit For 'выходим из цикла т.к. нету смысла искать дальше
        End If
    Next j
    If Not flagWeekday Then
        arrWorkDays(itsday) = arrWorkDays(itsday) + 1 'добавляем в массив
        If itsday <> 6 And itsday <> 7 Then
            workDays = workDays + 1 'если это не выходной, то увеличиваем счётчик рабочих дней
        End If
    End If
Next d
 
str = Cells(5, 12)
days = Split(str, ",")
 
For I = 0 To UBound(days)
    If IsNumeric(days(I)) Then
        If CInt(days(I)) > 0 And CInt(days(I)) < 8 Then
      'MsgBox (WeekdayName(CLng(days(I))) & " " & arrWorkDays(days(I))) (msgBox weekdays)
            Часы = Часы + arrWorkDays(days(I)) ' Выводит сумму дней недели в ячейку
        Else
            MsgBox ("Значение не является днём недели!")
        End If
        
    Else
        MsgBox ("Значение не является числом!")
    End If
Next I
 
End Function

Не могу выбор дней недели сделать аргументом.

Visual Basic
1
2
str = Cells(5, 12)
days = Split(str, ",")

Собственно только этого для счастья и не хватает.



0



70 / 57 / 24

Регистрация: 06.12.2015

Сообщений: 300

20.08.2018, 17:34

20

Цитата
Сообщение от PiLLyulk
Посмотреть сообщение

Не могу выбор дней недели сделать аргументом.

А что конкретно не получается? Ошибку какую-то выдает или что?



0



Содержание

  1. Метод WorksheetFunction.WorkDay (Excel)
  2. Синтаксис
  3. Параметры
  4. Возвращаемое значение
  5. Замечания
  6. Поддержка и обратная связь
  7. VBA Excel. Расчет рабочего времени
  8. Календарь рабочего времени
  9. Заполнение строки часов
  10. Поиск ближайшего рабочего дня функцией РАБДЕНЬ (WORKDAY)
  11. Name already in use
  12. VBA-Docs / api / Excel.WorksheetFunction.WorkDay.md
  13. Как определить последний рабочий день месяца(Excel, VBA, PowerQuery)

Метод WorksheetFunction.WorkDay (Excel)

Возвращает число, представляющее дату, представляющую указанное число рабочих дней до или после даты (начальной даты). Рабочие дни исключают выходные и любые даты, определенные как праздники. Используйте WorkDay , чтобы исключить выходные или праздничные дни при расчете сроков выполнения счета, ожидаемого времени доставки или количества выполненных работ.

Синтаксис

expression. WorkDay (Arg1, Arg2, Arg3)

Выражение Переменная, представляющая объект WorksheetFunction .

Параметры

Имя Обязательный или необязательный Тип данных Описание
Arg1 Обязательный Variant Start_date — дата, представляющая дату начала.
Arg2 Обязательный Variant Days — количество ненедельных и ненедельных дней до или после start_date. Положительное значение для дней дает дату в будущем; отрицательное значение возвращает прошлую дату.
Arg3 Необязательный Variant Праздники — необязательный список одной или нескольких дат для исключения из рабочего календаря, например государственных и федеральных праздников и плавающих праздников. Список может быть диапазоном ячеек, содержащих даты, или константой массива серийных номеров, представляющих даты.

Возвращаемое значение

Double

Замечания

Даты следует вводить с помощью функции DATE или в качестве результатов других формул или функций. Например, используйте date(2008,5;23) для 23-го дня мая 2008 г. Проблемы могут возникнуть, если даты вводятся в виде текста .

Microsoft Excel сохраняет даты как последовательные серийные номера, чтобы их можно было использовать в вычислениях. По умолчанию 1 января 1900 года — серийный номер 1, а 1 января 2008 года — серийный номер 39448, так как после 1 января 1900 г. это 39 448 дней. Microsoft Excel для Macintosh использует другую систему даты по умолчанию.

Visual Basic для приложений (VBA) вычисляет последовательные даты иначе, чем Excel. В VBA серийный номер 1 — 31 декабря 1899 года, а не 1 января 1900 года.

Если какой-либо аргумент не является допустимой датой, WorkDay возвращает #VALUE! значение ошибки.

Если start_date плюс дни возвращает недопустимую дату, WorkDay возвращает #NUM! значение ошибки.

Если число дней не является целым числом, оно усекается.

Поддержка и обратная связь

Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.

Источник

VBA Excel. Расчет рабочего времени

Расчет рабочего времени за период, ограниченный двумя датами, в течение одного года с помощью кода VBA Excel. Функция для расчета рабочего времени.

Календарь рабочего времени

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

Создавать такой календарь вручную, не считая протяжку дат, довольно долго и нудно. Поэтому мы создадим производственный мини-календарь программно.

Для создания календаря рабочего времени из кода VBA Excel сначала следует запустить процедуру DaysOfYear, которая заполнит строку дат:

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

Процедура DaysOfYear запускается из редактора VBA Excel и работает около минуты. Ускорить ее можно, используя массив, который заполняется датами и затем значения его элементов вставляются в диапазон дат.

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

Заполнение строки часов

Допустим, нам нужен календарь с пятидневной 40-часовой рабочей неделей, в котором необходимо указать 8 часов для будничных дней и 0 часов — для выходных.

Заполняем строку рабочего времени из кода VBA Excel с помощью процедуры WorkingTimeDay, которая в ячейки строки времени под ячейками с субботой и воскресеньем вставляет 0, а под ячейками с буднями — 8:

Источник

Поиск ближайшего рабочего дня функцией РАБДЕНЬ (WORKDAY)

Простая, но весьма частая задача у многих пользователей Microsoft Excel.

Предположим, что нам необходимо рассчитать срок доставки товара, зная дату отправки и длительность. Поскольку Excel на самом деле хранит даты как числа (количество дней с 1 января 1900 года), то простое сложение легко даст нам предполагаемую конечную дату доставки:

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

Первое, что обычно приходит в голову, это конструкция с вложенными проверками дней недели с помощью функций ЕСЛИ (IF) и ДЕНЬНЕД (WEEKDAY) . Что-то типа:

Т.е. если попали на субботу (ДЕНЬНЕД выдал 6 для даты доставки), то прибавляем еще 2 дня, чтобы сдвинуть на следующий понедельник. А если попали на воскресенье, то добавляем еще день. Не самая сложная формула.

На самом деле можно управиться существенно короче и изящнее 🙂

С 2007 года в Excel появилась функция РАБДЕНЬ (WORKDAY) , которая умеет сдвигать исходную дату на заданное количество рабочих дней, причем сдвиг может быть как положительным (в будущее), так и отрицательным (в прошлое). Фишка в том, что если взять предыдущий день от предполагаемой даты доставки и с помощью этой функции добавить к нему один рабочий день, то мы получим либо ту же самую дату (если были будни), либо ближайший понедельник (если доставка выпала на субботу или воскресенье). Что и требуется:

Приятным бонусом идет возможность указать список праздничных выходных дней, которые функция РАБДЕНЬ тоже будет воспринимать как нерабочие помимо суббот и воскресений. Диапазон с праздниками можно задать третьим аргументом:

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

Источник

Name already in use

VBA-Docs / api / Excel.WorksheetFunction.WorkDay.md

  • Go to file T
  • Go to line L
  • Copy path
  • Copy permalink

Copy raw contents

Copy raw contents

WorksheetFunction.WorkDay method (Excel)

Returns a number that represents a date that is the indicated number of working days before or after a date (the starting date). Working days exclude weekends and any dates identified as holidays. Use WorkDay to exclude weekends or holidays when you calculate invoice due dates, expected delivery times, or the number of days of work performed.

expression.WorkDay (Arg1, Arg2, Arg3)

expression A variable that represents a WorksheetFunction object.

Name Required/Optional Data type Description
Arg1 Required Variant Start_date — a date that represents the start date.
Arg2 Required Variant Days — the number of nonweekend and nonholiday days before or after start_date. A positive value for days yields a future date; a negative value yields a past date.
Arg3 Optional Variant Holidays — an optional list of one or more dates to exclude from the working calendar, such as state and federal holidays and floating holidays. The list can be either a range of cells that contain the dates or an array constant of the serial numbers that represent the dates.

Double

[!IMPORTANT] Dates should be entered by using the DATE function, or as results of other formulas or functions. For example, use DATE(2008,5,23) for the 23rd day of May, 2008. Problems can occur if dates are entered as text .

Microsoft Excel stores dates as sequential serial numbers so they can be used in calculations. By default, January 1, 1900 is serial number 1, and January 1, 2008 is serial number 39448 because it is 39,448 days after January 1, 1900. Microsoft Excel for the Macintosh uses a different date system as its default.

[!NOTE] Visual Basic for Applications (VBA) calculates serial dates differently than Excel. In VBA, serial number 1 is December 31, 1899, rather than January 1, 1900.

If any argument is not a valid date, WorkDay returns the #VALUE! error value.

If start_date plus days yields an invalid date, WorkDay returns the #NUM! error value.

If days is not an integer, it is truncated.

Источник

Как определить последний рабочий день месяца(Excel, VBA, PowerQuery)

Проблема получения последнего дня месяца довольно распространена и очень просто решается. Начиная с Excel 2007 можно без всяких доп.манипуляций использовать функцию КОНМЕСЯЦА (EOMONTH) :
=КОНМЕСЯЦА(ТДАТА();0)
=EOMONTH(NOW(),0)
ТДАТА (NOW) — возвращает текущую дату. Вместо неё можно указать любую дату и последняя дата месяца будет возвращена для указанной даты.
Для версий 2003 и ранее для использования КОНМЕСЯЦА (EOMONTH) необходимо для начала подключить надстройку Пакет анализа или же использовать чуть менее понятную формулу:
=ДАТА(ГОД(ТДАТА());МЕСЯЦ(ТДАТА())+1;0)
=DATE(YEAR(NOW()),MONTH(NOW())+1,0)
На самом деле данная формула проста, если разобраться детальнее. Функция ДАТА записывает в ячейку дату, на основании указанного года, месяца и дня. Мы для года берем год от текущей даты, далее берем месяц текущей даты и к месяцу прибавляем 1, чтобы получить следующий месяц. А потом для дня указываем 0, что заставляет Excel сдвинуть первую дату следующего месяца на один день назад. Таким образом и получается последняя дата месяца. Пошагово это выглядит так(если считать, что сегодня «22.10.2017»):
=ДАТА(ГОД(ТДАТА());МЕСЯЦ(ТДАТА())+1;0) =>
=ДАТА(ГОД(«22.10.2017»);МЕСЯЦ(«22.10.2017»)+1;0) =>
=ДАТА(2017;10+1;0) =>
=ДАТА(2017;11;0) здесь уже получится 01.11.2017, но 0 в качестве дня заставляет вернуться на день назад =>
=31.10.2017

Но есть более сложная проблема — получить дату последнего рабочего дня месяца. А это уже не так просто. Встроенных функций(вроде КОНМЕСЯЦА) для этого в Excel нет. А это значит опять придется танцевать с бубном.
Сразу возникает вопрос: а зачем это вообще может потребоваться? Например, для поиска счетов, отгрузка по которым производилась в последний рабочий день месяца, а оплаты(или документы на отгрузку) по некоторым пришли только в начале следующего. Так же такую функцию будет удобно применять для автоматического формирования платежек или накладных, если они должны быть оформлены именно последним рабочим днем месяца.
Чтобы получить именно корректную дату следует так же учесть и тот факт, что есть дни праздничные. И их тоже надо как-то учесть. Для этого я буду использовать отдельный лист Праздники , в столбце А которого записаны праздничные дни на пару лет. Также в этом диапазоне перечислены и все выходные. Сделано для более корректного подсчета дат, т.к. праздники могут быть перенесены, в результате чего рабочими становятся субботы или воскресенья. Если их не учитывать, то расчет будет неверным.

Из спортивного интереса создать такую функцию решил тремя способами:

Последний рабочий день при помощи стандартных функций Excel
В ходе некоторых экспериментов и манипуляций появилась такая формула:
=РАБДЕНЬ(
ЕСЛИ(ДЕНЬНЕД(КОНМЕСЯЦА( B4 ;0);2) B4 ;0);
КОНМЕСЯЦА( B4 ;0)-(ДЕНЬНЕД(КОНМЕСЯЦА( B4 ;0);2)-5));
0; Праздники!$A$2:$A$827)
=WORKDAY(
IF(WEEKDAY(EOMONTH(B4,0),2)
где Праздники!$A$2:$A$827 — ссылка на диапазон дат с праздниками
Здесь я так же использую КОНМЕСЯЦА для быстрого определения последней даты месяца.
Функция ДЕНЬНЕД (WEEKDAY) возвращает номер дня недели для указанной даты и нужна для того, чтобы определить — является последний день недели субботой или воскресеньем. Если нет, то возвращаем дату как есть, если это суббота или воскресенье — то отнимаем от даты либо 1 день, либо 2(если это СБ — то 1, если ВСК — то 2).
И только после этого применяем к полученной дате функцию РАБДЕНЬ (WORKDAY) , которая для последней даты месяца определяет, является ли она праздничной(на основании списка праздников Праздники!$A$2:$A$827 ). Если дата праздничная — то она уменьшается до тех пор, пока не достигнет рабочего дня. РАБДЕНЬ не принимает в расчет выходные, поэтому нам и нужны функции ЕСЛИ и ДЕНЬНЕД, прежде чем применить РАБДЕНЬ.

Однако сразу хочу оговорить, что в конкретно моем случае вычисление выходных дней при помощи ЕСЛИ и ДЕНЬНЕД несколько избыточно, т.к. в диапазоне с праздниками помимо непосредственно праздников у меня уже учтены все выходные дни. Т.е. по сути формула могла бы быть намного проще:
=РАБДЕНЬ(КОНМЕСЯЦА( B4 ;0); 0; Праздники!$A$2:$A$827)
=WORKDAY(EOMONTH(B4,0), 0, Праздники!$A$2:$A$827)
Но я все равно решил именно в статье привести формулу, которая смотрит и на дни недели, т.к. требования могут быть разными.

Т.к. Microsoft все же немного заботится о нас, то для пользователей версий Excel 2010 и более новых, в случае необходимости учитывать день недели прямо в формуле, можно использовать функцию РАБДЕНЬ.МЕЖД:
=РАБДЕНЬ.МЕЖД(КОНМЕСЯЦА(B4;0);0;1;Праздники!$A$2:$A$827)
=WORKDAY.INTL(EOMONTH(B4,0),0,1,Праздники!$A$2:$A$827)
РАБДЕНЬ.МЕЖД[дата; кол-во дней; выходные; праздники]
дата — дата, от которой необходимо отсчитать указанное кол-во дней
кол-во дней — количество дней, которые надо прибавить или отнять(отриц. число — отнимает дни от даты) от указанной даты
выходные — 1 = Суббота и Воскресенье, 2 — Воскресенье и Понедельник и т.д. Полный перечень есть в справке для функции и в выпадающей подсказке к функции при вводе.
праздники — ссылка на диапазон дат с праздниками
Достаточно указать последнюю дату месяца, указать для неё сдвиг на 0 дней, указать тип выходных и ссылку на диапазон дат с праздниками. Все уже сделано и все гораздо проще.

Последний рабочий день при помощи функции пользователя на VBA
Если использование VBA не является для вас проблемой, то можно применить функцию пользователя(UDF) для расчета последнего рабочего дня:

‘————————————————————————————— ‘ Author : The_Prist(Щербаков Дмитрий) ‘ Профессиональная разработка приложений для MS Office любой сложности ‘ Проведение тренингов по MS Excel ‘ http://www.excel-vba.ru ‘ WebMoney — R298726502453; Яндекс.Деньги — 41001332272872 ‘ Purpose: Функция получения последнего рабочего дня на основании указанной даты и списка праздников ‘————————————————————————————— Option Explicit Function ПоследнийРабочийДень(Дата As Date, Optional Праздники As Range = Nothing, Optional СистемныеВыходные As Boolean = False) Dim dd As Date, dres As Date Dim lWeekDay As Long dres = DateSerial(Year(Дата), Month(Дата) + 1, 0) If СистемныеВыходные Then lWeekDay = Weekday(dres, vbUseSystemDayOfWeek) If lWeekDay Alt + F11 ) -создать стандартный модуль(InsertModule) и в него вставить скопированный текст. После чего функцию можно будет вызвать из Диспетчера функций( Ctrl + F3 ), отыскав её в категории Определенные пользователем (User Defined Functions) .
Синтаксис функции:
=ПоследнийРабочийДень( B4 ;Праздники!$A$2:$A$827;0)

  • Дата( B4 ) — непосредственно дата или ссылка на ячейку с датой, последней рабочий день для которой необходимо вычислить. Будет рассчитан последний рабочий день для месяца указанной даты.
  • Праздники() — ссылка на диапазон ячеек, содержащих даты праздничных дней.
  • СистемныеВыходные(0) — ИСТИНА (TRUE или 1) или ЛОЖЬ (FALSE или 0) . Если указано как ЛОЖЬ, то при вычислении последнего рабочего дня не будут учитываться выходные. В этом случае они обязательно должны быть перечислены в списке Праздники. Если они не перечислены — то все дни недели считаются рабочими, кроме праздников. Если указано как ИСТИНА, то в качестве выходных будут применены те дни, которые установлены для календаря в операционной системе. Для русской локализации это как правило Суббота и Воскресенье.

Последний рабочий день при помощи PowerQuery
Самый экзотический метод. Если еще не знаете что такое PowerQuery — Power Query — что такое и почему её необходимо использовать в работе?.
Для начала необходимо загрузить список праздников.
Если список праздников еще не преобразован в умную таблицу, то на листе Праздники выделяем все ячейки с датами -переходим на вкладку Вставка (Insert)Таблица (Table) . Снимаем галку с пункта «Таблица с заголовками» —Ок:

Выделяем любую ячейку в созданной таблице праздников -переходим на вкладку Данные (Data или Power Query) и выбираем Из таблицы (From Table) .
Нажимаем в заголовке на значок календаря и в выпадающем списке выбираем тип Дата:

В правой части окна редактора изменяем название запроса(скорее всего там Таблица1) на Праздники:

Переходим на вкладку Главная, раскрываем пункт Закрыть и загрузить и выбираем Закрыть и загрузить в. :

В появившемся окне выбираем Только создать подключение и нажимаем Ок:

Теперь переходим на вкладку Данные(Data) -Получить данные -Из других источников -Пустой запрос. Переходим в расширенный редактор(вкладка ГлавнаяРасширенный редактор):

и вставляем туда следующий текст:
let
dNow = Date.From(DateTime.LocalNow()),
//dNow = Date.FromText(«2017-09-19»),
lastDay = Date.EndOfMonth(dNow),
WeekD = Date.DayOfWeek(lastDay,1),
dd = if WeekD
let
dAdd = value,
select_rows = Table.SelectRows(Праздники, each Record.Field(_, «Дата выходного дня») = dAdd),
count_rows = Table.RowCount(select_rows),
result = Date.AddDays(value,-count_rows)
in
result,
res_d = Table.FromValue(coun_dif(dd))
in
res_d

После этого можно на вкладке Главная нажать Закрыть и загрузить. Будет создан новый лист с одной ячейкой — датой последнего рабочего дня.
Чтобы приведенный запрос работал корректно, необходимо назвать столбец с праздничными датами «Дата выходного дня» . Либо изменить это название в самом запросе.
Если нужен последний рабочий день на конкретную дату, то необходимо убрать первую строку( dNow = Date.From(DateTime.LocalNow()), ) и убрать слеши вначале следующей строки:
let
dNow = Date.FromText(«2017-09-19»),
lastDay = Date.EndOfMonth(dNow),
WeekD = Date.DayOfWeek(lastDay,1),
dd = if WeekD
let
dAdd = value,
select_rows = Table.SelectRows(Праздники, each Record.Field(_, «Дата выходного дня») = dAdd),
count_rows = Table.RowCount(select_rows),
result = Date.AddDays(value,-count_rows)
in
result,
res_d = Table.FromValue(coun_dif(dd))
in
res_d
Если выходные не надо учитывать(чтобы суббота и воскресенье не рассчитывались автоматом в зависимости от дня недели), то запрос будет выглядеть так:
let
dNow = Date.FromText(«2017-09-19»),
dd = Date.EndOfMonth(dNow),
coun_dif = (value as date) as date =>
let
dAdd = value,
select_rows = Table.SelectRows(Праздники, each Record.Field(_, «Дата выходного дня») = dAdd),
count_rows = Table.RowCount(select_rows),
result = Date.AddDays(value,-count_rows)
in
result,
res_d = Table.FromValue(coun_dif(dd))
in
res_d

Реализацию всех приведенных решений можно скачать в приложенном файле
Скачать файл:

ПоследнийРабочийДень.xlsm (50,7 KiB, 614 скачиваний)

Статья помогла? Поделись ссылкой с друзьями!

Источник

Like this post? Please share to your friends:
  • Vba excel рабочие дни
  • Vba excel рабочая область
  • Vba excel работа формой
  • Vba excel работа текста
  • Vba excel публичная константа