Is there a way to hide (and then show again) track changes in Word before a desired date? - vba

I often have to check Word documents with multiple rounds of editing. To make things easier, I would like to be able to run a macro that prompts me to input a date and then any tracking before this date would be hidden, leaving only track changes made on or after the inputted date. Ideally, hitting the macro again would toggle the hidden track changes back to being shown.
I don't have an in-progress code as such, but do have two separate macros, each doing related things. The first is a simple toggle to hide and show insertions and deletions:
Sub ShowHideMarkup()
ActiveWindow.View.ShowInsertionsAndDeletions = Not _
ActiveWindow.View.ShowInsertionsAndDeletions
ActiveWindow.View.ShowFormatChanges = Not _
ActiveWindow.View.ShowFormatChanges
End Sub
And the second is one I've seen posted a few times online (created by Graham Mayor) - this one prompts for a date and then accepts earlier revisions:
Sub AcceptTrackingBeforeGivenDate()
Dim oRev As Revision
Dim oKeepDate As Date
Dim strRsp As String
While Not IsDate(strRsp)
strRsp = InputBox("Enter earliest date to keep", _
"Accept Changes Before Date", _
"1 Jan 2021")
If Len(strRsp) = 0 Then Exit Sub
Wend
oKeepDate = CDate(strRsp)
For Each oRev In ActiveDocument.Revisions
If oRev.Date < oKeepDate Then
oRev.Accept
End If
Next oRev
End Sub
I'm really not sure how to combine the two. Could anyone point me in the right direction?
Many thanks in advance!
Luke

Your two macros cannot be combined to do as you want. The:
first simply toggles the track-changes view on/off for all tracked changes.
second simply accepts all changes before a specified date, meaning they no longer exist in the document and, unless all the 'accepts' are undone or discarded (by not saving the document), provides no means of 'unhiding' those changes.
Word has no capacity to display some tracked changes and hide others based on the date.
The kludgy workaround I had in mind is equivalent to what the second macro does - without saving the modified document.
Do note that, even without using Track Changes, Word allows you to use its document comparison feature to compare two versions of the same document (e.g. the current version and a version in your backups). You could do the same thing by saving daily/weekly versions of the documents (different filenames, of course), to compare any two versions against each other.

Related

How to Accept All Changes In Selection?

I am trying to accept all changes in a selection, in Word 2013.
I used the macro recorder and it generated the following code (it can also be found at https://learn.microsoft.com/en-us/office/vba/api/word.revisions.acceptall)
Selection.Range.Revisions.AcceptAll
However, it will not work unless I physically select each letter
But if I use the built in buttons in the 'Changes' group within the 'Review' tab, I don't have to physically select the entire letter. I just need to select any part of the change and it will accept the change.
Why does the macro version not perform like the UI option?
That is odd behavior. The UI must be doing something like the below, but whoever built the macro recorder missed it.
Public Sub AcceptSelection()
Dim rev As Revision
For Each rev In Selection.Range.Revisions
rev.Accept
Next rev
End Sub
That code will accept any revisions in the selection, even partial ones.

VBA loop through non-patterned files in folder (seek for opinions) [EDIT]

I am here for seeking any advice or opinion as I want to loop through every excel files in folder. As you can see from my attached picture, my excel files are different both in file types (.xls <> .xlsx) and filename (especially on 2018). I also need to loop through "Revised" or "revised" files as well since it is possibly that any file will be revised next time.
And yes, I also did some research on this. My understanding is I need to modify all of the file names into the pattern one before build up a VBA to loop. At first, I thought about decomposing all filenames and put it back in pattern form, but it sound too idealistic. Another way is using the date in each file to label the workbook name, but again I found that those date had different styles. Some files label the date by using string such as "January 2012" or "March 2014", while the others using the date form such as "19/08/2013".
Therefore, I would be appreciated if anyone could suggest me on;
How can I handle with the different file name (.xls and .xlsx) within the same VBA?
How should I deal with these different file names (some files have "revised" at the back; some do not have "-" between "Cons" and date; and some use month name instead of number)? Are they any pattern that I overlook?
Please noted that I am just a newbie VBA coder, so it would be great if you left your answers with an explanation or any kind of examples.
Many thanks.
--------------------------------------------------------[EDIT]-------------------------------------------------------------------
First of all sorry for my poor explanation before. I provided too few information to understand overall picture. Let's start this over again.
My data are about steel consumption which release from the authority
every month. My task is to gather all of these data (such as
production, import, export and consumption of every data in each
row) and generate into time series pattern (please see attached
excel screen)
As it is possibly that these data will be revised anytime, I thus
decide to download all of these file every time in every month (one
file per one month). In addition to those revised file, the
authority will unexpectedly rename those file for example, from
"Cons 201601.xlsx" into "Cons 201601 - revised.xlsx)". This make me
more difficult to work on this (please see attached folder for
reference).
Moreover, this authority seems to have a problem with file naming as
they had different pattern of filename in the past compare to the
present ones. Example is per below table; Cons 201701-Revised.xlsx
Cons 201710-Revised1.xlsx
Cons 201711.xlsx
Cons-200902.xls
Cons-201212_revise.xls
Cons-201401-revised.xls
I mention above file name in order to create a VBA to loop through
these file, select some content and paste into another workbook in
chronological order. This means that I cannot use "Loop while or Do
while function" in my VBA. At first I decided to use two integer
variables, both of which were set for years and months
(e.g. For i = 2009 to 2018 and For j = 1 to 12) in order to created the system of filename (such as filename = "Cons" & "-" & i & j). But,
as I stated before, non-patterned name by the authority had
prevented me from creating this kind of loop.
I also tried to use the date in cell B2 in figure 1 to label the
date in order to create the loop which I already explained before.
However, again, the authority did not use the same pattern to date
month and year. After I checked with many file, these are example of
the date style in cell B2 January 2012 (string)
February 2009 (string)
Jan-16 (1/1/2016 date in custom format)
Given above limitations, could you guys again suggest me any possible
way to create chronological loop so as to copy and paste data to another
workbook to form a set of time series data for each product?
Thank you for your kind help :)
Firstly, use FileSystemObject (include a reference to Microsoft Scripting Runtime in your VBA project) which has some helpful functions within it. You could always code your own, but why reinvent the wheel in this case?
Don't have time to codes something this morning, so here is the pseudocode:
Open a Folder using your known filepath
Loop through all the files in the Folder (For each f in Folder.Files
extract the date code from your filename (e.g. using RegEx)
Add to a collection (e.g. array or Dictionary item) of the filename and the extracted date code (your key).
(end loop)
Sort your collection based on the extracted date code
This now gives you an ordered list of files, which you can open in turn and extract the data. An added bonus is that the key in the collection gives you a consistent date representation which you can use as an index in your collated information.
If you just want to loop through all files in folder use this:
dim file as variant
file = Dir("<PathToFolder>")
While (file <> "")
'Your logic here
file = Dir
wend

Saving cell Presets in a dropdown list

At the moment I have created a spreadsheet which takes a bunch of inputs, runs them through a list of formulas, and then spits out the results onto a "report" worksheet.
I've been manually saving each of these reports as separate CSVs but I was hoping for a better method moving forward as it is getting quite tiring to have to open 10 CSVs when i do my monthly reports.
I am looking for a way to start saving all of these reports into a "database". My hope to to have one cell be for an user entry name and for two buttons. One to save the current report under the name entered by the user, and two to remove old records. I would then be able to revisit old entries by selecting them in the dropdown.
I've dabbled with VBA and Macros in the past but this is a little more complicated than what I've dealt with in the past. Looking for some help/direction.
Thanks for your time!
Depending on how your reports need to be used, you might find it satisfactory to simply make your data into one big Excel Table ( Insert Tab > Table ). When you do this, Excel will automatically fill-down any formulas that you enter in a column, and also show the formula using the headers instead of A1-style references.
I use this format, adding Y under Remove from Active List on each line that is already done. Then whenever I save the file or look at it for today's status, I filter out what's old and just look at the new. The other filters enable copy-pasting or printing whatever arrangement I like.
The filters and other things in the table can be referenced in VBA as Sheets("ThisSheet").ListObjects(1), which is an object with a number of useful properties and methods.
For VBA information, read more here: https://www.thespreadsheetguru.com/blog/2014/6/20/the-vba-guide-to-listobject-excel-tables
This is my code for auto-filtering the table to hide inactive items at time of save. You add it at ThisWorkbook in the VBA editor:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Sheets("Sheet1").Activate
SelectedCell = ActiveCell.Address 'this saves your screen selection for after the filtering
ActiveSheet.ListObjects(1).Range(1, 1).Select
If ActiveSheet.ListObjects(1).AutoFilter.FilterMode = True Then
ActiveSheet.ListObjects.Item(1).AutoFilter.ShowAllData
End If
A = ActiveSheet.ListObjects(1).Range.Rows(1).Find("Remove from List").Column - _
ActiveSheet.ListObjects(1).Range.Column + 1
ActiveSheet.ListObjects(1).Range.AutoFilter field:=A, Criteria1:="="
Range(SelectedCell).Select
End sub

Trouble with Copying VBA Code

I've been working on an independent project for a client of mine. They wanted to produce a button that, upon the user-click, it would open up a user-form and have a variety of macro-related options to choose from: a drop-down list, checkbox, option select button, etc.
I created a test formula and submitted it to the client; they enjoyed it thoroughly and decided to sent me a file to 'copy & paste' my original code within their excel file.
Problem is; because I'm a tad bit inexperienced with VBA I've run into a problem where once I click the button - the user form doesn't show up.
Below is a Dropbox link of the original file I created and it's original code; as well as the file that I am trying to copy.
Any help would be all welcome and appreciated.
Link to dropbox: https://www.dropbox.com/sh/l1t37lz8uritrua/AAAdWPGvw0GDZ6hW4SwmbBdRa?dl=0
OriginalProject.xlsm has a form named honor_roll_form which contains 100 lines of code.
CopyOfOriginal.xlsm has a form named UserForm1 which contains no useful code.
I do not believe there is any method of directly copying user forms from one workbook to another. Instead
Within VB Editor of OriginalProject.xlsm, select honor_roll_form.
Click File then Export File and save the form on your desktop or where ever you like.
You will now have two files on your desktop; one with an extension of frm and one with an extension of frx.
Within VB Editor of CopyOfOriginal.xlsm, click File then Import file.
Import honor_roll_form.frm
When I try clicking button "Honor Roll", I get "Method or data member not found" for project1Box. I will investigate after dinner (18:57 here) unless you tell me you already know why I am getting this error.
Extra comments in response to request from OP
It is late here but I have started looking down sub execute_button_Click within the second CopyOfOriginal.xlsm. I will comment on what I see even if it is not directly relevant to the non-execution of the macro.
If you open the VB Editor and look on the left you will see the Project Explorer. Near the top you will see:
Microsoft Excel Objects
Sheet1 (Sheet1)
I have always found this confusing. The first “Sheet1” is Excel’s Id for the worksheet and cannot be changed. The second “Sheet1” is the default name for the worksheet which can be changed. You can write Sheet1.Range("A1") or Worksheets("Sheet1").Range("A1"). That is: you can reference a worksheet by its Id or its name. You have named a variable of type Worksheet as Sheet1. Using Excel’s names as variable names can lead to bizarre errors so it is important to avoid doing anything like this.
It is better to always use meaningful names. At the moment, you know what Sheet1 means but if you come back to this macro in six or twelve months will you remember. I would use a variable as you have but I would name it WshtCis208 or WshtVBAProg or something similar.
Set ID = Range(Sheet1.Cells(2, 1), Sheet1.Cells(52, 1)) could be written as:
With WshtCis208
Set ID = Range(.Cells(2, 1), .Cells(52, 1))
End With
Using With statements produces faster code and, almost always, code that it easier to read.
“52” is the current bottom row for this table. Will you amend the macro for them every time they add or remove a student? There are several techniques for finding the last row, none of which is perfect in every situation. The technique that is the most convenient most of the time is:
Const ColCis208Id as Long = 1
Const ColCis208MidTermExam as Long = 5
Dim RowCis208Last as Long
RowCis208Last = .Cells(.Rows.Count, ColCis208Id).End(xlUp).Row
At the moment, column 1 is the Id column. It is perhaps unlikely that the Id column will move but it is very likely that some of the others columns will move when some new column is identified as useful. Do you want to scan the code trying to decide which 5s refer to the MidtermExam column when a Project3 column is added?
Constants allow you to name literals that might change. It makes your code easier to read and saves so much pain when a value changes.
.Rows.Count gives the number of rows in a worksheet for the current version of Excel so .Cells(.Rows.Count, ColCis208Id) identifies the bottom cell of column 1. End(xlUp).Row says go up until you hit a cell with a value and returns its row number. It is the VBA equivalent of Ctrl+Up.
The next statement subjectCount = … fails because projectBox does not exist on the form. You have changed the captions but not the names.
As far as I can see the form fails to execute because you have started updating it but have not finished.

Working with multiple discontinuous selection

I'm trying to do something with a multiple selection. I wanna add some text before every selected paragraph but, when I select multiple discontinuous paragraphs, if I do Selection.Paragraphs.Count I always get "1".
How could I work with all paragraphs apart?
Example:
Paragraph1(Selected first)
Paragraph2
Paragraph3(Selected second)
What I got when I try to add some text at the beginning of these paragraphs:
Paragraph1
Paragraph2
TEXTParagraph3
What I really want to obtain:
TEXTParagraph1
Paragraph2
TEXTParagraph3
I'm working like this:
sub x()
dim p as paragraph
for each p in selection.paragraphs
p.range.insertbefore("TEXT")
next
End sub
Word simply cannot do what you'd like for it to do. Developers have wished for this since multiple selections were introduced in 2003 (I think it was, might have been version 2007). Word's object model simply does not support it.
If this is something you want to provide to the user to make life easier you'll need to give the tool a way to mark the paragraphs so your code can recognize them. You could provide a macro, for example, that assigns an incrementing bookmark name to each selection (the user selects, then runs your macro; repeat for each paragraph). Your code can then address each bookmark and perform the actions. To make this more user friendly you can assign the macro to a keyboard shortcut and/or a button in the Ribbon/QAT and/or the right-click menu.