Имеем таблицу данных, по горизонтали дни месяца, по вертикали объекты, на пересечении забиваем в ячейку руками сотрудника. Необходимо: 1 На втором листе выводить эти данные построчно, как в примере. То есть искать в таблице не пустую ячейку и когда нашли, брать дату и объект и делать это новой строкой на листе2. 2 Самое сложное и важное! Если мы меняем в таблице лист1 уже существующую информацию (например удаляем Иванова), информация не должна пропадать из таблицы 2. То есть там должна быть история.
Надеюсь понятно написал.
Если первый пунк решаем формулами, то второй ставит меня в тупик.
Помогите пожалуйста решить следующую задачу.
Имеем таблицу данных, по горизонтали дни месяца, по вертикали объекты, на пересечении забиваем в ячейку руками сотрудника. Необходимо: 1 На втором листе выводить эти данные построчно, как в примере. То есть искать в таблице не пустую ячейку и когда нашли, брать дату и объект и делать это новой строкой на листе2. 2 Самое сложное и важное! Если мы меняем в таблице лист1 уже существующую информацию (например удаляем Иванова), информация не должна пропадать из таблицы 2. То есть там должна быть история.
Надеюсь понятно написал.
Если первый пунк решаем формулами, то второй ставит меня в тупик. VVeps
Такой простенький вариант в модуле первого листа. КодНайм второго обозван shIst [vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) Dim d_ As Range Application.ScreenUpdating = 0 r0_ = 5 r1_ = Range("A" & Rows.Count).End(xlUp).Row c0_ = 2 c1_ = Cells(r0_ - 1, Columns.Count).End(xlToLeft).Column Set d_ = Intersect(Target, Range(Cells(r0_, c0_), Cells(r1_, c1_))) If Not d_ Is Nothing Then dc_ = d_.Cells.Count With shIst r11_ = .Range("A" & Rows.Count).End(xlUp).Row For i = 1 To dc_ .Range("A" & r11_ + i) = Cells(r0_ - 1, d_(i).Column).Value .Range("B" & r11_ + i) = Cells(d_(i).Row, c0_ - 1).Value .Range("C" & r11_ + i) = d_(i).Value Next i End With End If End Sub
[/vba]
Такой простенький вариант в модуле первого листа. КодНайм второго обозван shIst [vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) Dim d_ As Range Application.ScreenUpdating = 0 r0_ = 5 r1_ = Range("A" & Rows.Count).End(xlUp).Row c0_ = 2 c1_ = Cells(r0_ - 1, Columns.Count).End(xlToLeft).Column Set d_ = Intersect(Target, Range(Cells(r0_, c0_), Cells(r1_, c1_))) If Not d_ Is Nothing Then dc_ = d_.Cells.Count With shIst r11_ = .Range("A" & Rows.Count).End(xlUp).Row For i = 1 To dc_ .Range("A" & r11_ + i) = Cells(r0_ - 1, d_(i).Column).Value .Range("B" & r11_ + i) = Cells(d_(i).Row, c0_ - 1).Value .Range("C" & r11_ + i) = d_(i).Value Next i End With End If End Sub
еще вариант Сводная + подключение + небольшой макрос для обновления (в модуле Лист2) [vba]
Код
Private Sub Worksheet_Activate() Dim LastRefreshed As Date With Sheets("Лист3").PivotTables(1) LastRefreshed = .RefreshDate: .RefreshTable Do While .RefreshDate <= LastRefreshed DoEvents Loop End With Me.ListObjects(1).QueryTable.Refresh 0 End Sub
[/vba]
еще вариант Сводная + подключение + небольшой макрос для обновления (в модуле Лист2) [vba]
Код
Private Sub Worksheet_Activate() Dim LastRefreshed As Date With Sheets("Лист3").PivotTables(1) LastRefreshed = .RefreshDate: .RefreshTable Do While .RefreshDate <= LastRefreshed DoEvents Loop End With Me.ListObjects(1).QueryTable.Refresh 0 End Sub
Boroda, можно вас попросить мемного изменить макрос под вновь окрывшиеся обстоятельста. Пример во вложении. Возникла необходимость добавить строчки. Теперь поиск фамилий нужно делать по каждой третьей строке начиная с пятой. И огромная просьба, напишите короткие комментарии в макросе какая строка что делает. Я хочу понять макрос, пока не очень получилось
krosav4ig, спасибо, но под новый файл (во вложении), как я понимаю, метод со сводной таблицей не подходит.
Спасибо большое! Как вы это делаете?
Boroda, можно вас попросить мемного изменить макрос под вновь окрывшиеся обстоятельста. Пример во вложении. Возникла необходимость добавить строчки. Теперь поиск фамилий нужно делать по каждой третьей строке начиная с пятой. И огромная просьба, напишите короткие комментарии в макросе какая строка что делает. Я хочу понять макрос, пока не очень получилось
krosav4ig, спасибо, но под новый файл (во вложении), как я понимаю, метод со сводной таблицей не подходит.VVeps
Такой вариант (с объяснялками). Пока писал их, понял, что немного лишнего наваял (одновременно и n, и f не обязательно), но ладно, так тоже нормально. [vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) 'При каждом изменении на листе Dim d_ As Range 'договариваемся, что d_ будет обозначением ячеек Application.ScreenUpdating = 0 'отключаем автообновление экрана r0_ = 5 'начальная строка r1_ = Range("B" & Rows.Count).End(xlUp).Row 'конечная строка по столбцу В c0_ = 3 'начальный столбец c1_ = Cells(r0_ - 1, Columns.Count).End(xlToLeft).Column 'конечный столбец по строке r0_-1 (4 строка) f_ = "ФИО" 'где будем ловить изменения n_ = 3 'кол-во строк в блоке (часы, машина, ФИО) Set d_ = Intersect(Target, Range(Cells(r0_, c0_), Cells(r1_, c1_))) 'пересечение С5:AG16 и того диапазона, 'где мы изменили данные обзываем "d_" (сделано для возможности вводить сразу несколько строк и/или столбцов - например, копи-паст) If Not d_ Is Nothing Then 'если не d = пусто (другими словами - если d не пусто) dc_ = d_.Cells.Count 'кол-во ячеек в d With shIst 'для листа с кодовым именем shIst. Теперь его имя не пишем, а обозначаем первой точкой, вот так - .Range(что-то r11_ = .Range("A" & Rows.Count).End(xlUp).Row 'конечная строка по столбцу А For i = 1 To dc_ 'i меняется от 1 до dc и для каждого из i If Cells(d_(i).Row, c0_ - 1) = f_ Then 'если в той же строке и столбце В значение f, то ii = ii + 1 'к счетчику ii прибавляем 1 .Range("A" & r11_ + ii) = Cells(r0_ - 1, d_(i).Column).Value 'в первой пустой ячейке столбца А листа shIst 'вставляем значение из строки 4 того столбца, где изменение на Лист1 .Range("B" & r11_ + ii) = Cells(d_(i).Row - n_ + 1, c0_ - 2).Value 'в первой пустой ячейке столбца В листа shIst 'вставляем значение из столбца А [строки с изменением минус 2], где изменение на Лист1 .Range("C" & r11_ + ii) = d_(i).Value 'в первой пустой ячейке столбца С листа shIst 'вставляем изменяемое значение из Лист1 End If 'окончание второго ЕСЛИ Next i 'i становится i+1 End With 'заканчиваем With по листу shIst End If 'окончание первого ЕСЛИ End Sub 'окончание макроса
Такой вариант (с объяснялками). Пока писал их, понял, что немного лишнего наваял (одновременно и n, и f не обязательно), но ладно, так тоже нормально. [vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) 'При каждом изменении на листе Dim d_ As Range 'договариваемся, что d_ будет обозначением ячеек Application.ScreenUpdating = 0 'отключаем автообновление экрана r0_ = 5 'начальная строка r1_ = Range("B" & Rows.Count).End(xlUp).Row 'конечная строка по столбцу В c0_ = 3 'начальный столбец c1_ = Cells(r0_ - 1, Columns.Count).End(xlToLeft).Column 'конечный столбец по строке r0_-1 (4 строка) f_ = "ФИО" 'где будем ловить изменения n_ = 3 'кол-во строк в блоке (часы, машина, ФИО) Set d_ = Intersect(Target, Range(Cells(r0_, c0_), Cells(r1_, c1_))) 'пересечение С5:AG16 и того диапазона, 'где мы изменили данные обзываем "d_" (сделано для возможности вводить сразу несколько строк и/или столбцов - например, копи-паст) If Not d_ Is Nothing Then 'если не d = пусто (другими словами - если d не пусто) dc_ = d_.Cells.Count 'кол-во ячеек в d With shIst 'для листа с кодовым именем shIst. Теперь его имя не пишем, а обозначаем первой точкой, вот так - .Range(что-то r11_ = .Range("A" & Rows.Count).End(xlUp).Row 'конечная строка по столбцу А For i = 1 To dc_ 'i меняется от 1 до dc и для каждого из i If Cells(d_(i).Row, c0_ - 1) = f_ Then 'если в той же строке и столбце В значение f, то ii = ii + 1 'к счетчику ii прибавляем 1 .Range("A" & r11_ + ii) = Cells(r0_ - 1, d_(i).Column).Value 'в первой пустой ячейке столбца А листа shIst 'вставляем значение из строки 4 того столбца, где изменение на Лист1 .Range("B" & r11_ + ii) = Cells(d_(i).Row - n_ + 1, c0_ - 2).Value 'в первой пустой ячейке столбца В листа shIst 'вставляем значение из столбца А [строки с изменением минус 2], где изменение на Лист1 .Range("C" & r11_ + ii) = d_(i).Value 'в первой пустой ячейке столбца С листа shIst 'вставляем изменяемое значение из Лист1 End If 'окончание второго ЕСЛИ Next i 'i становится i+1 End With 'заканчиваем With по листу shIst End If 'окончание первого ЕСЛИ End Sub 'окончание макроса
Благодаря подсказкам удалось встроить макрос в свой файл. Спасибо еще раз. Вопрос для интереса, мы когда удаляем старые значения, макрос создает новые строки на листе shIst. Я понимаю. что он работает при любых изменениях даипазона, но слишком ли сложно сделать, чтобы строки не создавались, если значение ячейки равно ="" (пусто)?????
В данном варианте я могу войти в ячейку и выйти ничего не меняя - будет новая строка.
В принципе и так работает, но перфикционизм, такой перфикционизм.
Супер!
Благодаря подсказкам удалось встроить макрос в свой файл. Спасибо еще раз. Вопрос для интереса, мы когда удаляем старые значения, макрос создает новые строки на листе shIst. Я понимаю. что он работает при любых изменениях даипазона, но слишком ли сложно сделать, чтобы строки не создавались, если значение ячейки равно ="" (пусто)?????
В данном варианте я могу войти в ячейку и выйти ничего не меняя - будет новая строка.
В принципе и так работает, но перфикционизм, такой перфикционизм.VVeps