Выходные дни в excel vba

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]

Содержание

  1. Метод WorksheetFunction.WorkDay (Excel)
  2. Синтаксис
  3. Параметры
  4. Возвращаемое значение
  5. Замечания
  6. Поддержка и обратная связь
  7. метод WorksheetFunction.WorkDay_Intl (Excel)
  8. Синтаксис
  9. Параметры
  10. Возвращаемое значение
  11. Замечания
  12. Поддержка и обратная связь
  13. Функция Weekday
  14. Синтаксис
  15. Settings
  16. Возвращаемые значения
  17. Замечания
  18. Пример
  19. См. также
  20. Поддержка и обратная связь
  21. VBA Excel. Расчет рабочего времени
  22. Календарь рабочего времени
  23. Заполнение строки часов
  24. Name already in use
  25. VBA-Docs / api / Excel.WorksheetFunction.WorkDay.md

Метод 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 и обратная связь.

Источник

метод WorksheetFunction.WorkDay_Intl (Excel)

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

Синтаксис

expression. WorkDay_Intl (Arg1, Arg2, Arg3, Arg4)

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

Параметры

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

Номер выходного дня Выходные дни
1 или опущено Суббота, Воскресенье
2 Воскресенье, понедельник
3 Понедельник, вторник
4 Вторник, среда
5 Среда, четверг
6 Четверг, Пятница
7 Пятница, суббота
11 Только воскресенье
12 Только понедельник
13 Только вторник
14 Только среда
15 Только четверг
16 Только пятница
17 Только суббота
Arg4 Необязательный Variant Праздники — необязательный набор из одной или нескольких дат, которые должны быть исключены из календаря рабочего дня. Праздники — это диапазон ячеек, содержащих даты или константу массива последовательного значения, представляющего эти даты. Порядок дат или серийных значений в праздники может быть произвольным.

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

Double

Замечания

Если start_date выходит за пределы диапазона для текущего базового значения даты, WorkDay_Intl возвращает #NUM! значение ошибки.

Если какая-либо дата в праздники выходит за пределы диапазона для текущего базового значения даты, WorkDay_Intl возвращает #NUM! значение ошибки.

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

Если строка выходных данных имеет недопустимую длину или содержит недопустимые символы, WorkDay_Intl возвращает #VALUE! значение ошибки.

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

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

Источник

Функция Weekday

Возвращает значение переменной Variant (Integer), отображающее дни недели.

Синтаксис

Weekday(date, [ firstdayofweek ])

Синтаксис функции Weekday состоит из таких именованных аргументов:

Part Описание
дата Обязательный аргумент. Переменная, числовое выражение, строковое выражение или любое выражение, отображающее дату. Если аргумент date содержит Null, возвращается значение Null.
первый_день_недели Необязательный аргумент. Константа, задающая первый день недели. Если она не указана, им является vbSunday.

Settings

Аргумент первый_день_недели может принимать следующие значения:

Константа Значение Описание
vbUseSystem 0 Используются параметры API NLS.
vbSunday 1 Воскресенье (по умолчанию)
vbMonday 2 Понедельник
vbTuesday 3 Вторник
vbWednesday 4 Среда
vbThursday 5 Четверг
vbFriday 6 Пятница
vbSaturday 7 Суббота

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

Функция Weekday возвращает такие значения:

Константа Значение Описание
vbSunday 1 Воскресенье
vbMonday 2 Понедельник
vbTuesday 3 Вторник
vbWednesday 4 Среда
vbThursday 5 Четверг
vbFriday 6 Пятница
vbSaturday 7 Суббота

Замечания

Если свойство Calendar имеет значение григорианский, возвращаемое целое число представляет григорианский день недели для аргумента date.

Если задан календарь хиджра, возвращаемое целое число означает день недели по календарю хиджра, соответствующий аргументу date. Для дат по календарю хиджра числовым аргументом является любое числовое выражение, представляющее дату или время с 1 января 100 года (2 августа 718 года по грегорианскому календарю) по 4 марта 9666 года (31 декабря 9999 года по грегорианскому календарю).

Пример

В этом примере функция Weekday возвращает день недели по указанной дате.

См. также

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

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

Источник

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

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

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

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

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

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

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

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

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

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

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

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

Источник

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.

Источник

В одном из заказов недавно столкнулся с проблемой получения праздничных дней согласно утвержденному производственному календарю. Да, я знаю, что в компаниях он может быть свой, отличный от опубликованного государством. И смысла как-то получать список праздничных дат с общедоступных порталов не было. Но вот именно сейчас потребовался именно общедоступный опубликованный календарь, чтобы можно было его автоматом скачать и применить. И оказалось, что это тоже не самая простая задача: многие календари в сети либо в формате 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) —InsertModule. Вставляем туда код выше полностью. Или скачать файл ниже — там уже все сделано удобно и красиво:
Скачать файл с кодом:

В случае с 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»)). Это самая важная строка в текущей задаче — она получает исходный текст страницы сайта в виде разбитого на строки текста, в котором потом можно будет просматривать и искать нужное нам
Power Qwery FromBinary function
а дальше по сути идет тоже самое, что делалось кодом 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 и просмотреть по шагам все действия:
Шаги запроса Power Qwery
Но если вдруг это надо будет — пишите в комментариях, постараюсь описать процесс наглядно(в будущем подготовлю видеоурок на данную тему).

0 / 0 / 0

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

Сообщений: 86

1

Заполнение выходных дней

19.08.2019, 15:20. Показов 1859. Ответов 7


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

Добрый день, коллеги)

Передо мной встала такая задача:
Есть таблица некоторой отчётностью с датами. Есть все даты, кроме выходных дней. Хотелось бы написать такой макрос, который с 01.04.2019 по сегодняшний день будет копировать данные с ближайшей слева пятницы в субботу и воскресение.

Спасибо большое заранее.



0



0 / 0 / 0

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

Сообщений: 86

19.08.2019, 15:31

 [ТС]

2

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



0



1813 / 1135 / 346

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

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

20.08.2019, 17:43

3

Hikitosik, а что за сложности?
1.ищем пустой столбец по ячейке первой строки
2.копируем столбцы пятничного блока вместе с пустым столбцом блока и дважды вставляем.
3. заменяем в первом вставленном блоке пятничную дату + 1 день, во втором блоке +2
4.лучше это делать справа



1



0 / 0 / 0

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

Сообщений: 86

21.08.2019, 12:13

 [ТС]

4

Это всё классно, уже попробовал реализовать. Всё можно сделать циклом, поскольку компаний константное количество. Даже формулу можно вывести

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



0



1813 / 1135 / 346

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

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

21.08.2019, 16:20

5

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

копировать и вставлять вручную

Что ж тоже вариант, только перед этим включить запись макроса, а после выполнения всех действий по копированию делаем Остановить запись. Получили макрос. Только вместо номера конкретного столбца ставите переменную, в которую вставляете индекс пустого столбца. А поиск пустой ячейки первой строки ну совсем просто — последовательной проверкой на космическую пустоту. В макрос вставляете добавление даты этого нового столбца на ещё 1 день.



0



0 / 0 / 0

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

Сообщений: 86

21.08.2019, 20:34

 [ТС]

6

Наверно, мы друг друга не совсем понимаем)
В самой таблице явно не указано, какого дня нет. Просто идут даты: 01.02, 02.02, 05.02,…

Плюс проблема возникает в том, что таблица растёт в ширь. То есть необходимо будет приписывать справа к ней недостающие даты. Пока не осознал, как это правильно сделать



0



КостяФедореев

Часто онлайн

792 / 530 / 238

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

Сообщений: 1,820

22.08.2019, 00:07

7

Hikitosik, попробуйте

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
Sub Макрос1()
Dim i As Date
Dim z, x, y As Long
z = z + 1
x = "01.04.2019"
segognya = "06.04.2019" 'Date
For i = x To segognya
    For y = 1 To 13
        If Cells(1, y + z) <> i Then
           Columns(y + z).Select
           Selection.Insert Shift:=xlToLeft, CopyOrigin:=xlFormatFromLeftOrAbove
           Columns(y + z).Select
           Selection.Insert Shift:=xlToLeft, CopyOrigin:=xlFormatFromLeftOrAbove
           Cells(1, y + z) = i
           Cells(2, y + z) = "Компания " & y
           If y = 13 Then
           Columns(y + z + 1).Select
           Selection.Insert Shift:=xlToLeft, CopyOrigin:=xlFormatFromLeftOrAbove
           End If
        End If
    Next y
    z = z + y
Next i
End Sub

Добавлено через 2 минуты
Hikitosik, в строке 6 можете изменить дату до которой нужно проверить или поставить значение Date и она всегда будет сегодняшнее число.

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



2



1813 / 1135 / 346

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

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

22.08.2019, 05:10

8

Hikitosik, у вас там в примере идет пустой столбец, я ориентировался по нему. Если пропущена дата, то это тоже просто, проверяешь разницу дат и, если больше 1, то делаешь то, что я писал. Мне хотелось, чтобы вы попробовали сами справиться и помочь в случае чего. Но если КостяФедореев взялся, то он вам всё напишет без проблем и без обучения. Удачи.



2



Расчет рабочего времени за период, ограниченный двумя датами, в течение одного года с помощью кода 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.


Понравилась статья? Поделить с друзьями:
  • Выходной интервал в excel это
  • Выходной интервал в excel что такое
  • Выход текста за ячейку excel
  • Выход на одну excel
  • Выучить программу excel самостоятельно онлайн бесплатно с нуля