Выбрать дату в календареВыбрать дату в календаре

Страницы: 1
Совместное редактирование файлов Excel, Поиск вариантов одновременной работы в Exel модели без shared desk
 
Идеальный компромисс — шаблоны Excel с макросом синхронизации с мастер-файлом через локальную сеть или промежуточные файлы.

Там можно много чего "доделать"...
Ведение лога изменений (например, лог-файл .csv кто и когда залил данные).
Уведомление об ошибках и несоответствиях (например, если строка не заполнилась до конца).
Встроенная валидация данных (чтобы не сломать формулы или не вставить нечисловое значение в ячейку расчёта).

Каждый сотрудник работает с локальной копией (шаблоном), где есть:
  • только своя часть бюджета;

  • встроенный VBA-макрос, который по кнопке (или автоматически по времени) забирает/отправляет данные в централизованный мастер-файл на защищённом сетевом диске или FTP.

Вариант 1. Через общий сетевой диск (например, \\server\budget\master.xlsm)
  1. Пользователь открывает свою копию.

  2. Макрос по кнопке:

  • вставляет данные в нужный раздел (например, по имени пользователя или ID)
  • сохраняет и закрывает мастер.
  • собирает нужные данные (таблицы, значения ячеек)
  • открывает мастер-файл в фоновом режиме через VBA
____________________________________________________________­______

(на мой взгляд самый безопасный)
Вариант 2. Работать через модель данных с обработкой шаблонов макросом в вид базы данных. С каждого шаблона создается "база данных" или просто подключение, затем собираете всё "в едино" через модель данных" и обрабатываете уже агрегированную информацию в мастер-файле.

Как создать макрос который будет дублировать определенные ячейки автоматически?
 
Цитата
написал:
для начала понять бы как именно Вы делаете.  P.S. Очень элегантно было приложить файл без единой строки кода  поэтому можно лишь на всякий случай уточнить: код куда вставляете? Надо в модуль листа: правая кнопка мыши на ярлыке листа -Исходный текст(или Посмотреть код). Подробнее про модуль листа:  Модуль листа
Поддержу... потому что судя по всему код то рабочий у человека. Только видимо не на листе вставлен..

Ну и сам по себе код в сообщении чуть с ошибкой. Dim rng as range надо строчкой ниже
Код
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim Rng As Range
    If Not Intersect(Target, Range("C16,C17,C19,C20,C23,C24,C25,C27")) Is Nothing Then
        Set Rng = Range("H16,H17,H19,H20,H23,H24,H25,H27")
        Application.EnableEvents = False
        Rng.Value = Target.Value
    End If
    Application.EnableEvents = True
End Sub

Еще бы и не забыть сохранить в формате .xlsm
Правда я не знаю точно ли надо чтобы при изменении любой ячейки в C16,C17,C19,C20,C23,C24,C25,C27 менялись сразу все ячейки в диапазоне H16,H17,H19,H20,H23,H24,H25,H27 на значение из ячеек первого диапазона.. Т.е. Если в C17 поменять дату, то такая же дата будет в H16,H17,H19,H20,H23,H24,H25,H27, не смотря на то, что в других C ячейках другие даты...

Возможно нужен такой код (похожий как у Дмитрий(The_Prist) Щербаков)
Код
Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("C16,C17,C19,C20,C23,C24,C25,C27")) Is Nothing Then
        Dim targetRow As Long
        targetRow = Target.Row
        
        Application.EnableEvents = False
        Range("H" & targetRow).Value = Target.Value
        Application.EnableEvents = True
    End If
End Sub
Изменено: Михаил - 26.09.2024 12:10:14
Макрос по условию, Выполнение и запрет на выполнение макроса
 
Цитата
написал:
В результате ничего не происходит и присылает ошибку "400"
Гугле в помощь:
  1. Проблемы с активным диапазоном: Возможно, на момент выполнения макроса ничего не выделено, либо выделение не соответствует ожидаемым ячейкам.
  2. Неверная работа с ActiveCell: Возможно, в момент выполнения ActiveCell не относится к нужной строке или вовсе не установлена.
  3. Ошибки при копировании и вставке: Ошибка может возникнуть, если диапазон для вставки не подходит или не существует.
Код
Sub Трудоемкость()

    Application.ScreenUpdating = False

    Dim cell As Range
    Dim ws As Worksheet
    
    ' Указываем явно рабочий лист "МАРШРУТ"
    Set ws = Sheets("МАРШРУТ")
    
    ' Проверяем, есть ли выделенные ячейки
    If Selection Is Nothing Then
        MsgBox "Ошибка: Нет выделенных ячеек."
        Application.ScreenUpdating = True
        Exit Sub
    End If
    
    ' Проверяем, что все выделенные ячейки находятся в диапазоне B3:B
    For Each cell In Selection
        If Intersect(cell, ws.Range("B3:B" & ws.Rows.Count)) Is Nothing Then
            MsgBox "Ошибка: Выделенные ячейки должны быть в диапазоне B3:B."
            Application.ScreenUpdating = True
            Exit Sub
        End If
    Next cell

    ' Копирование выделенных ячеек
    Selection.Copy
    
    ' Вставка в ячейку A7 на листе "МАРШРУТ"
    ws.Range("A7").PasteSpecial Paste:=xlPasteValues
    
    ' Проверяем, что ActiveCell находится на рабочем листе
    If Not Intersect(ActiveCell, ws.UsedRange) Is Nothing Then
        ' Выполняем расчет для 22-й ячейки строки с ActiveCell
        With ActiveCell.EntireRow
            .Cells(1, 22).Value = WorksheetFunction.Sum(ws.Range("G10:G14")) * ws.Range("A5") / 60
        End With
    Else
        MsgBox "Ошибка: Неверная активная ячейка."
        Application.ScreenUpdating = True
        Exit Sub
    End If

    Application.ScreenUpdating = True
    MsgBox "Операция выполнена успешно."
    
End Sub
Я тут добавил проверок условий и еще пару ошибок со вставкой исправил.

Если ничего не выделено, макрос завершится. Переключение на явное использование листа ws = Sheets("МАРШРУТ"). Использование PasteSpecial с параметром xlPasteValues - это необходимо, чтобы вставлять только значения. ActiveCell проверка активной ячейки -  находится ли на рабочем листе.
Данные, Проверка данных, Список, Заполнение данных пользователем
 
Прикрепил файл с решением, всё просто, ну если я правильно понял.

P.S.
Я потом только понял, что надо. Без приватного кода VBA вряд ли получится решить такую задачу...  
Изменено: Михаил - 24.09.2024 18:51:10
Извлечь определенный текст из ячейки с текстом, Как извлечь определенный текст из ячейки с текстом?
 
Можно создать пользовательскую функцию в VBA, используя регулярные выражения. весь фокус в строке  :excl:  regex.Pattern = "\b(DN\d+|PN\d+)\b" :excl:  .
Код
Function ExtractDNPN(text As String) As String
    Dim regex As Object
    Dim matches As Object
    Dim match As Object
    Dim result As String
    
    Set regex = CreateObject("VBScript.RegExp")
    regex.Global = True
    regex.IgnoreCase = True
    regex.Pattern = "\b(DN\d+|PN\d+)\b"
    
    Set matches = regex.Execute(text)
    
    For Each match In matches
        result = result & match.Value & " "
    Next match
    
    ExtractDNPN = Trim(result)
End Function
Создаешь модуль куда вставляешь этот макрос.
Затем в ячейке можешь использовать формулу
Код
=ExtractDNPN(B2) 
Макрос по условию, Выполнение и запрет на выполнение макроса
 
Примерно такой код, мб сложновато, но я расписал примечания.
Код
Sub Трудоемкость()

Application.ScreenUpdating = False

' Переменные для проверки
Dim cell As Range
Dim found As Boolean

' Проверяем наличие текста "проверить каталог!" в диапазоне B3:B
found = False
For Each cell In Sheets("МАРШРУТ").Range("B3:B" & Rows.Count)
    If cell.Value = "проверить каталог!" Then
        found = True
        Exit For ' Останавливаем цикл, если найдено совпадение
    End If
Next cell

If found Then
    MsgBox "Ошибка: В диапазоне B3:B найдена ячейка с текстом 'проверить каталог!'."
    Exit Sub
End If

' Проверяем, что выделение находится в диапазоне B3:B
For Each cell In Selection
    If Not Intersect(cell, Sheets("МАРШРУТ").Range("B3:B" & Rows.Count)) Is Nothing Then
        ' Если ячейка в диапазоне, продолжаем выполнение
    Else
        MsgBox "Ошибка: Выделенная область должна быть в диапазоне B3:B."
        Exit Sub
    End If
Next cell

' Копирование выделенной области и вставка на листе "МАРШРУТ"
Selection.Copy
Sheets("МАРШРУТ").Range("A7").PasteSpecial

' Вычисление значения на основе диапазона G16:G22 и ячейки A5
With ActiveCell.EntireRow
    .Cells(1, 23).Value = WorksheetFunction.Sum(Sheets("МАРШРУТ").Range("G16:G22")) * Sheets("МАРШРУТ").Range("A5") / 60
End With

Application.ScreenUpdating = True

End Sub
Изменение значений в именованных диапазонах, Это скорее интересная тема, чем вопрос.
 
Цитата
написал:
Извините, а можно на него взглянуть?
Строго не судите, я как смог сделал. Тут 2 макроса, один экспортирует всё на отдельный лист, второй меняет данные. Там был ряд проблем с вытаскиванием диапазонов (пришлось чуть проверок добавить) и примечания по-моему я так и не доделал, но оно работает. Комментарии в коде где посчитал важным написал.
Код
Sub ExportNamedRangesToSheet()
    Dim ws As Worksheet
    Dim nName As Name
    Dim i As Integer
    Dim rng As Range
    Dim refersToValue As String

    On Error Resume Next
    Set ws = ThisWorkbook.Sheets("NamedRanges")
    If ws Is Nothing Then
        Set ws = ThisWorkbook.Sheets.Add
        ws.Name = "NamedRanges"
    End If
    On Error GoTo 0

    ws.Cells.Clear

    ws.Cells(1, 1).Value = "Имя"
    ws.Cells(1, 2).Value = "Значение"
    ws.Cells(1, 3).Value = "Диапазон"
    ws.Cells(1, 4).Value = "Область"
    ws.Cells(1, 5).Value = "Примечание"

    totalNames = ThisWorkbook.Names.Count

    ' Заполняем таблицу именованными диапазонами
    i = 2
    currentIndex = 0 ' Счётчик для прогресса
    For Each nName In ThisWorkbook.Names
        currentIndex = currentIndex + 1 ' Обновляем прогресс

        Application.StatusBar = "Экспорт именованных диапазонов: " & currentIndex & " из " & totalNames & " (" & Format(currentIndex / totalNames, "0%") & ")"

        ws.Cells(i, 1).Value = nName.Name ' Имя

        On Error Resume Next
        refersToValue = "'" & nName.RefersTo ' Преобразуем в строку, добавляя апостроф для безопасности
        On Error GoTo 0

        If Len(refersToValue) > 0 Then
            ws.Cells(i, 2).Value = refersToValue
        Else
            ws.Cells(i, 2).Value = "" ' Оставляем пустым, если ошибка
        End If

        On Error Resume Next
        Set rng = Nothing
        Set rng = nName.RefersToRange
        On Error GoTo 0
        
        If Not rng Is Nothing Then
            ws.Cells(i, 3).Value = rng.Worksheet.Name & "!" & rng.Address ' Включаем имя листа
        Else
            ws.Cells(i, 3).Value = "Не применимо" ' Если это не диапазон
        End If

        ' Определяем, глобальный ли это диапазон или на уровне листа
        If nName.Parent Is ThisWorkbook Then
            ws.Cells(i, 4).Value = "Глобальный (Workbook)"
        Else
            ws.Cells(i, 4).Value = nName.Parent.Name ' Лист, если диапазон на уровне листа
        End If
        
        ws.Cells(i, 5).Value = "" ' Примечание
        i = i + 1
    Next nName

    Application.StatusBar = False

    MsgBox "Именованные диапазоны экспортированы на лист 'NamedRanges'.", vbInformation
End Sub

Код
Sub UpdateNamedRangesFromSheet()
    Dim ws As Worksheet
    Dim nName As Name
    Dim lastRow As Long
    Dim i As Long
    Dim newRange As String
    Dim oldName As String
    Dim totalRows As Long
    Dim currentIndex As Long

    Set ws = ThisWorkbook.Sheets("NamedRanges")

    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
    totalRows = lastRow - 1
    currentIndex = 0

    ' Проходим по каждому имени и обновляем диапазон (можно оставить только те строки которые необходимо изменить)
    For i = 2 To lastRow
        currentIndex = currentIndex + 1

        Application.StatusBar = "Обновление именованных диапазонов: " & currentIndex & " из " & totalRows & " (" & Format(currentIndex / totalRows, "0%") & ")"

        oldName = ws.Cells(i, 1).Value
        newRange = ws.Cells(i, 3).Value

        ' Ищем соответствующее имя и обновляем его
        For Each nName In ThisWorkbook.Names
            If nName.Name = oldName Then
                On Error Resume Next
                nName.RefersTo = "=" & newRange ' Обновляем диапазон
                On Error GoTo 0
                Exit For
            End If
        Next nName
    Next i

    Application.StatusBar = False

    MsgBox "Именованные диапазоны обновлены на основе изменений на листе.", vbInformation
End Sub
Изменение значений в именованных диапазонах, Это скорее интересная тема, чем вопрос.
 
Цитата
написал:
И все ж меня сильно интересует сколько ж имен в книге?
Имен в книге около 500, я сожалению отправить рабочий файл со структурой не могу из-за NDA даже не структуру файла, там очень много расчетов на нескольких листах около 2700 строк и столбцы от A до EB, за счёт чего долго и происходит замена имен с включенным пересчетом я думаю.
А прогресс бар не то чтобы нужен :-) я просто его сделал. Достаточно было бы строки состояния стандартной.
Изменение значений в именованных диапазонах, Это скорее интересная тема, чем вопрос.
 
Цитата
написал:
вывести списком всех на лист, там вручную под контролем поменять любым способом, затем макросом всё залить назад.
А я уже реализовал такой вариант на следующий день после того как прочёл сообщение от Дмитрий(The_Prist) Щербаков, задумался как контролировать процесс удобнее и надёжнее в плане результата. Т.е. сейчас есть вариант с выводом на отдельный лист всех имен с диапазонами и сохранением после изменений отдельным макросом.
Изменение значений в именованных диапазонах, Это скорее интересная тема, чем вопрос.
 
Цитата
написал:
нужно только для вывода DEBUG , а оно нужно на постоянной основе?
Если вкратце, то можно и без него

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

Если убрать это строчку, то можно просто выполнять замену без проверки. Тогда макрос заменит значение, даже если искомое значение не было найдено (просто ничего не изменится в таком случае).
Изменение значений в именованных диапазонах, Это скорее интересная тема, чем вопрос.
 
Цитата
написал:
Например, если надо заменить "F1:" на "F2:" в диапазонах вида "F1:F100","F1:G100", "F1:AA100" - замены будут произведены так же и в диапазоне вида "AF1:AF100"(он станет выглядеть как "AF2:AF100"). А это не всегда желательно, если предполагались замены только диапазонов столбца F.
это так и будет да, тут надо пользоваться этим как функцией "замена" в екселе... надо подумать прежде чем менять :-)
А теперь надо подумать еще как докрутить так, чтобы менялось именно то, что надо... и особенно интересно как сработает с учетом знаков " * " и " ? " ... хм. Хорошо что ночей впереди полно...
Изменение значений в именованных диапазонах, Это скорее интересная тема, чем вопрос.
 
Цитата
написал:
Михаил , ну, тогда уж и код процедуры UpdateProgressBar выкладывайте, раз решили свой код выложить
Ох, совсем забыл пока пост писал :-) отредактировал первое сообщение, ниже под основным кодом и прогресс бар теперь есть :-)  
Изменение значений в именованных диапазонах, Это скорее интересная тема, чем вопрос.
 

Ночные приключения с макросами: или как простая задача вылилась в ночной марафон из VBA

Привет всем! Поделюсь историей, как я, в который раз, провёл ночь, сражаясь с Excel. Обычная задача раздвинуть диапазоны в файле. Вроде ничего особенного, не правда ли? Зашёл в диспетчер имен, поправил пару диапазонов — и готово. Ха! Ага, сейчас...

Оказалось, что в файле именованных диапазонов столько, что вручную это править — можно успеть выучить китайский язык, а потом всё равно не закончить. Ну ладно, думаю, не беда, надо просто быстренько макрос накатать. Простой, как дверь, макрос, который возьмёт и поменяет диапазоны с одного столбца на другой. Пять минут делов. Кто бы сомневался, да?

Код
Sub UpdateNamedRanges()
    Dim nName As Name
    Dim oldAddress As String
    Dim newAddress As String
    
    For Each nName In ThisWorkbook.Names
        oldAddress = nName.RefersTo
        
        If InStr(1, oldAddress, "$EB$", vbTextCompare) > 0 Then
            newAddress = Replace(oldAddress, "$EB$", "$EC$")
            
            nName.RefersTo = newAddress
            
            Debug.Print "Имя: " & nName.Name & " изменено с " & oldAddress & " на " & newAddress
        End If
    Next nName

    MsgBox "Обновление диапазонов завершено!", vbInformation
End Sub

Пишу макрос, и тут начинается... Какой диапазон менять? На что менять? Давай прогресс-бар добавим, чтобы было видно, как он этот диапазон величественно раздвигает. Ну и, конечно, не забываем о всплывающем окне, которое спросит у пользователя, что вообще менять. Потому что, ну, вы же понимаете — без этого никуда. И так уже два часа ночи, а я всё ещё пишу этот "простой" макрос, который, очевидно, должен был быть готов уже три чашки кофе назад.

Но самое интересное начинается, когда вдруг вспоминаешь, что макрос-то у тебя в "Книга1", а вот работаешь ты в "Книга2". Конечно, Excel должен был догадаться сам и всё сделать правильно, но нет. Так что сидишь и дописываешь, чтобы он работал в активной книге, потому что, естественно, Excel не в состоянии сам понять, что от него хотят. Простая задача, думал я. Пара минут, говорил я.

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

Код
Sub UpdateNamedRangesWithProgressBar()
    Dim nName As Name
    Dim oldAddress As String
    Dim newAddress As String
    Dim totalNames As Long
    Dim currentIndex As Long
    Dim searchValue As String
    Dim replaceValue As String
    Dim activeWorkbook As Workbook

    Set activeWorkbook = Application.ActiveWorkbook

    searchValue = InputBox("Введите значение, которое нужно заменить (например, $EB$):", "Значение для замены")
    If searchValue = "" Then Exit Sub ' Отмена, если ничего не введено

    replaceValue = InputBox("Введите новое значение, на которое нужно заменить (например, $EC$):", "Новое значение")
    If replaceValue = "" Then Exit Sub ' Отмена, если ничего не введено

    totalNames = activeWorkbook.Names.Count
    currentIndex = 0

    'прогресс-бар
    Set ProgressForm = VBA.UserForms.Add("ProgressForm")
    ProgressForm.ProgressBar.Width = 0
    ProgressForm.ProgressLabel.Caption = "Обновление диапазонов..."
    ProgressForm.Show vbModeless

    For Each nName In activeWorkbook.Names
        currentIndex = currentIndex + 1
        UpdateProgressBar currentIndex, totalNames
        oldAddress = nName.RefersTo

    ' Проверяем, содержит ли диапазон искомое значение и меняем его на новое
        If InStr(1, oldAddress, searchValue, vbTextCompare) > 0 Then
            newAddress = Replace(oldAddress, searchValue, replaceValue)

            nName.RefersTo = newAddress

            Debug.Print "Имя: " & nName.Name & " изменено с " & oldAddress & " на " & newAddress
        End If
    Next nName

    ' Закрываем форму прогресс-бара после завершения
    Unload ProgressForm
    MsgBox "Обновление диапазонов завершено!", vbInformation
End Sub

Sub UpdateProgressBar(currentIndex As Long, totalNames As Long)
    ' Обновление ширины прогресс-бара и текста на форме
    If Not ProgressForm Is Nothing Then
        With ProgressForm
            .ProgressBar.Width = (.ProgressFrame.Width - 2) * (currentIndex / totalNames)
            .ProgressLabel.Caption = "Обновление: " & currentIndex & " из " & totalNames & _
                                     " (" & Format(currentIndex / totalNames, "0%") & ")"
            DoEvents ' Обновление интерфейса
        End With
    End If
End Sub

Чтобы это всё заработало, нужно создать форму --> еще небольшая инструкция:


   
Скрытый текст
Изменено: Михаил - 18.09.2024 10:41:36
Увеличение и уменьшение графика выполнения работ в процентах по месяцам, Увеличение и уменьшение графика выполнения работ в процентах по месяцам
 
Цитата
написал:
Привет  математической формулой кривой было б наверное лучше чем с "эталоном"
Очень круто вышло, спасибо :-)
Можете объяснить суть формулы которую вы сделали? Судя по всему через деление "целевого" периода на "эталонный" определяется позиция через индекс в эталонной строке и как то остаток распределяется .... жалко ariexcel нет чтобы разложить формулу..
Увеличение и уменьшение графика выполнения работ в процентах по месяцам, Увеличение и уменьшение графика выполнения работ в процентах по месяцам
 
Всем привет.
Возникла проблема с формированием типовых графиков выполнения работ по месяцам.
Необходимо создать графики выполнения работ на каждое количество месяцев согласно "эталону" выделенным желтым цветом в файле строка 15.

Использую строку 15 где проценты выполнения разбиты на 30 месяцев необходимо создать новые "линейки" выполнения, которые будут ужиматься либо увеличиваться именно в таком же "темпе" т.е. всегда возникает появление одного "горба/скачка" выполнения постепенно, а затем постепенное понижение выполнения в процентах.
Вот не могу понять с помощью какой формулы можно это сделать... Так чтобы ориентироваться на эталон и указывать необходимое количество месяцев в столбце "B"

Для примера в строка 13, 14 и 5 расписал руками проценты, но это надо делать с помощью формул...

Помогите решить задачку, пожалуйста. Спасибо.
Страницы: 1
Наверх