#excel #vba #footer #worksheet
#excel #vba #нижний колонтитул #рабочий лист
Вопрос:
Я использую Excel 2007 с рабочей книгой, в которой много листов. Мне нужно иметь дату последнего сохранения листа — в нижнем колонтитуле. Мне удалось найти следующее:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
With ws.PageSetup
.LeftFooter = "Last Save Time: amp;T"
.RightFooter = "Last Save Date: amp;D"
End With
Next ws
Set ws = Nothing
End Sub
Это изменяет каждый рабочий лист. Мне это нужно, чтобы изменить только тот лист, который был отредактирован (поэтому на каждом листе может быть другая дата).
Возможно ли это вообще? Должен ли я использовать ячейку вместо нижнего колонтитула? Или мне нужно создать несколько рабочих книг?
Спасибо!
Ответ №1:
Как было предложено Remnant, наилучшим подходом было бы использовать Worksheet_Change
событие. Это означает, что вам нужен этот код VBA
Private Sub Worksheet_Change(ByVal Target As Range)
With Me.PageSetup
.LeftFooter = "Last Change Time: " amp; Format(VBA.Time, "hh:mm:ss")
.RightFooter = "Last Change Date: " amp; Format(VBA.Date, "dd/mm/yy")
End With
End Sub
в каждом из ваших листов. Это событие возникает только при изменении содержимого ячеек, а не при изменении выделения, так что это может быть то, что вы хотите.
Remnant также написал, что это будет «сложно настроить», если у вас много листов. Я думаю, это зависит от того, что вы называете «многими». Для 20 ~ 40 листов приведенный выше код можно легко скопировать вручную на каждый лист за несколько минут.
Если у вас уже есть рабочая книга и много (скажем, более 40) листов, то может быть хорошей идеей добавить код программно. Добавьте в свою книгу отдельный модуль, содержащий этот код, и запустите его один раз:
Option Explicit
Sub InsertCode()
Dim VBProj As Object
Dim VBComp As Object
Dim CodeMod As Object
Dim sh As Worksheet
Dim LineNum As Long
Set VBProj = ActiveWorkbook.VBProject
For Each sh In ThisWorkbook.Sheets
Set VBComp = VBProj.vbcomponents(sh.Name)
Set CodeMod = VBComp.CodeModule
With CodeMod
.DeleteLines 1, .CountOfLines
LineNum = .CreateEventProc("Change", "Worksheet")
LineNum = LineNum 1
.InsertLines LineNum, "Me.Pagesetup.LeftFooter = ""Last Change Time: "" amp; Format(VBA.Time, ""hh:mm:ss"")"
.InsertLines LineNum 1, "Me.Pagesetup.RightFooter = ""Last Change Date: "" amp; Format(VBA.Date, ""dd/mm/yy"")"
End With
Next
End Sub
Это добавит событие «Worksheet_Change» сверху в раздел кода каждого листа.
Комментарии:
1. Нравится! Я должен сказать, что я редко шел по пути написания кода VBA с помощью кода VBA, но в данном случае это кажется разумным вариантом. Спасибо, что поделились своими мыслями.
2. Спасибо @Remnant и Доку Брауну! На данный момент я реализовал этот код на одном листе, и он работает отлично. Извините, что не отвечаю на ваши вопросы, я не знал, как войти в систему. Мои файлы cookie были удалены, поскольку я не знал, что они использовались сайтом для входа в систему. Спасибо за быстрые ответы 🙂
Ответ №2:
Причина, по которой он изменяет каждый рабочий лист, заключается в том, что вы выполняете «Для каждого WS в этой рабочей тетради.Рабочие листы». Измените это, чтобы найти только тот лист, который вы хотите изменить, и все будет готово.
Например, если у вас нет ссылки на лист, который вы хотите изменить, сохраните цикл For Each, но вместо того, чтобы изменять каждый цикл, выполните проверку на листе, чтобы увидеть, тот ли это, который вы хотите. Если это так, измените нижний колонтитул. В противном случае игнорируйте это.
Комментарии:
1. Извините, но я полагаю, что вы упускаете суть вопроса.
Ответ №3:
Одним из вариантов может быть обновление нижнего колонтитула при каждом изменении листа. Это будет означать, что на отдельных листах будут разные даты / время в зависимости от того, когда они были обновлены.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
With Sh.PageSetup
.LeftFooter = "Last Save Time: " amp; Format(VBA.Time, "hh:mm:ss")
.RightFooter = "Last Save Date: " amp; Format(VBA.Date, "dd/mm/yy")
End With
End Sub
Затем пользователь может сохранить книгу в обычном режиме.
Дает ли это вам то, что вам нужно?
Комментарии:
1. Возможно, это сработает, но одна проблема здесь заключается в том, что Excel примет просто изменение текущего выделения в качестве изменения рабочего листа.
2. @Doc Brown — Согласен. Единственное другое решение, которое я могу придумать, это использовать
Worksheet_Change
событие на каждом листе. OP говорит, что у него «много листов», поэтому было бы сложно настроить, но, возможно, самое надежное решение. Есть ли у вас мнение о том, как лучше поступить в этом случае?3. немного подумав об этом, я нашел решение, используя ваше предложение (см. Мой ответ).