Write in specific point of a docx document using vba - vba

I need to modify a template document (docx) automatically, according to info I've read into some text files and I'm using VBA for this.The template document has a predefined record, which looks like this:
description: first description which can take more rows
...
author: the author
date: the date
...
What I need is copying the previous line below the first one, as many times as many text file I have, and complete each one whit info I've copied into strings. So,for example, if I have 3 text file I'll have the previous line three times, like this:
description: first description
...
author: the first author
date: the date in the first file
description: second description
...
author: the second author
date: the date in the second file
description: third description
...
author: the third author
date: the date in the third file
where the first one is already there and I need to repeat it twice.
How can I tell Word to copy and write in specific points of the document?
I've thought something like the following:(The code probably is not correct, I'll put it there to explaying my idea)
For i = 1 To n(number of text file)
ActiveDocument.Range(Start:=ActiveDocument.Paragraphs(Index).Range.Start
End:=ActiveDocument.Paragraphs(Index+3).Range.End).Select
Selection.Copy
ActiveDocument.Paragraphs(Index+4).Select
Selection.Paste
Next i
the previous was for copying the record.
Now I have to fill that records writing the info after title:, author: and date: of each one, so something like:
For i=1 To n
ActiveDocument.Paragraphs(Index(i)+1).Words(2) = description(i)
ActiveDocument.Paragraphs(Index(i)+2).Words(2) = author(i)
ActiveDocument.Paragraphs(Index(i)+3).Words(2) = date(i)
Next i
where description, author and date are text string I already have.
Does that make any sense or I'm taking a wrong way? Is there any smarter VBA objects I could use?

Unfortunately, I don't have enough points yet to add this as a comment, where it would actually belong...
Which version of Word are you using?
Do you have any influence on the construction of the template, so that you could, for example, add bookmarks such as iDevelop suggests or possibly ContentControls (would be better)?
If you have no influence then it would be better for you to plan entering the data in each "copy" loop.
Note: I hope you're using Documents.Add to create new documents from the template so that you're not actually changing the template?

Related

Replace zero length mail merge field with user input

I have a MS Word template where I have certain mail-merge fields and one of those fields in the source doucment is sometimes empty. I am using below IF condition and taking user's input for the date field but I cannot update the source mail merge document with this information.
If Len(ActiveDocument.MailMerge.DataSource.DataFields("startDate").Value) < 1 Then
InputStartDate = Format(InputBox("Enter Commenced date ..."), "mm/dd/yyyy")
ActiveDocument.MailMerge.DataSource.DataFields("startDate").Value = InputStartDate
End If
I get an error here that says mail merge source doucment field connot be edited or is locked, something like this.
Is there any way through which I could either update the source field and through application refresh method, I populate that mail merge field with this user input date?
Alternatively I could otherwise add a few lines of code to perform following steps:
1- Save this document (using Saveas2 method) as ".docx" by converting it from ".docm"
2- Break the mail merge connection through VBA code
3- Select all mail merge fields and using Sendkeys "CTRL+SHIFT+F9" covert all of them to normal strings.
4- Make that particular mail-merge field a Bookmark field and then finally update that bookmark field with the user input.
This sounds like a longer route of getting a simple empty mail merge field issue fixed but this is so far all that I could think of. If you have any better suggestion, please let me know.
Instead of vba, do this with fields. Then it becomes part of the Mail Merge.
{ IF { MergeField startDate } > 0 "{MergeField starttDate }" "{ FillIn "What is the Start Date?" }" }
This will trigger the Fill-In field unless there is content in the startDate field for the record.
Here is documentation on the Fill-In Field.
Here is documentation on the IF Field.
Here is my tutorial on the Ask and Fill-In Fields.
Here is my article on Dealing With Fields in Microsoft Word.
Here is Word MVP Paul Edstein's Tutorial on Mailmerge Tips and Tricks.

Change Heading Number copied from another document

How can I change the Heading Number with VBA code?
For example, "1.1 Computer system"
I'd like to change "1.1" to "1.2".
I can read it with:
Selection.Paragraphs(1).Range.ListFormat.ListString
I can't find a way to change it.
Basic Function Test
1.1. LED Function Test Purpose: To make sure all the LED Functions are working as the Product Specification Resource Requirements:
The context is shown above. Sometimes, I copy from another document. The pasted heading number is not correct.
I tried to record the macro but the recorded macro is empty.
To force Heading 2 to start the numbering from 1.2, all you need is:
ActiveDocument.Styles(wdStyleHeading2).ListTemplate.ListLevels(2).StartAt = 2
Your update shows you're trying to do something quite different, however.
The only reliable way to retain the original numbering when copying/pasting between documents is to either:
convert the source numbering to static text before copying; or
paste the copied content as unformatted text.

MS-Word - Pulling down cell content to the next page if a table is broken by a page-break

I have a table in Word that has column titles. When the page breaks the table rolls over to the next page and the headers repeat. However, I also have section titles that are important to see as well. If you look at the example below, I have the section '2' at the top next to sub-section 'C'.
a) I will be generating MHTML dynamically for import into Word so if it is possible to generate MHTML that will enable the above then that would be great. Otherwise ...
b) Is there any way within Word to manually or using VBA mark up the sections so they know to roll over to the next page automatically, so that the table will update itself if there are any changes to page-break locations. Alternatively...
c) I might have to write some VBA that checks that the section numbers are in the right place every time the VBA code is manually run, although I suspect that might start to get messy as I will also have to remove any existing 'pulled' section numbers that might have been inserted.
Thanks

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

How to automatically bookmark and hyperlink matching text in VBA

I'm trying to create a script in VBA for a Word document that bookmarks and hyperlinks matching strings with numbering to a location later in the document. Right now I have two sets of matching for matching text that looks like this (sometimes with hundreds of more entires):
Contents
'There is a bookmark here named "InpCon"
4326: Info 1
32534: Info 2
7980: Info 3
Body
'There is a bookmark here named "InpBod"
4326: Info 1
32534: Info 2
7980: Info 3
This is what I'm trying to do:
Table of Contents
'There is a bookmark here named "InpCon"
4326: Info 1 'Hyperlink to Bookmark Name: "Info1"
32534: Info 2 'Hyperlink to Bookmark Name: "Info2"
7980: Info 3 'Hyperlink to Bookmark Name: "Info3"
Body
'There is a bookmark here named "InpBod"
4326: Info 1 'Bookmark Name: "Info1"
32534: Info 2 'Bookmark Name: "Info2"
7980: Info 3 'Bookmark Name: "Info3"
I'm trying to implement this at the end of a larger script I have. The larger script copies everything under the "InpBod" bookmark to the "InpCon" bookmark at one point. I don't know if inputting a process there to do this would be more efficient.
Basically, my VBA knowledge is pretty limited. I've tried looking for something that accomplishes this task, but haven't found anything. I'd paste my code, but it's pretty large and on a stand alone system. This would shave hours off my week if I can get it done. Can someone help me out or point me in the right direction? Thanks you in advance.
Don't "manually" generate "InpCon". Use Word to generate the TOC. When generating "InpBod", everytime you come across something you want to link to, mark it and then actomatically generate the TOC. Two possible ways to do so:
Use heading styles and then generate a TOC. Everytime you stumble upon an entry to be marked, mark the paragraph as a heading Selection.Range.Paragraphs.Style = ActiveDocument.Styles(wdStyleHeading1). You may want to change the default heading styles. Then insert a TOC at the beginning.
Use bookmarks if the document uses headers for something else. Everytime you stumble upon an entry to be marked, create a bookmark like this: ActiveDocument.Bookmarks.Add Range:=Selection.Range.Collapse wdCollapseEnd, Name:=**THEBOOKMARKNAME**. Notice that you'll have to remove spaces and that kind of stuff for the bookmark name. Then iterate thorugh all the activedocument.Bookmarks inserting the links using Selection.InsertCrossReference ReferenceType:="Bookmark", ReferenceKind:= _
wdContentText, ReferenceItem:=ITEM, InsertAsHyperlink:=True, _
IncludePosition:=False, SeparateNumbers:=False, SeparatorString:=" "
The macro recorder will expose every object you need to do this.
Using newer info from the comments:
The Word's list object model is pretty well illustrated here: Looping a Word macro over many list paragraphs causes memory issue and here http://oreilly.com/catalog/writewordmacro/chapter/ch17.html with more detail. Here's the proper documentation: http://msdn.microsoft.com/en-us/library/aa223019(v=office.11).aspx
You should loop through the lists collection members (for what I gather you should only have one list, the InpBod list). Then loop through the paragraphs in that list selecting each like this:
Dim para as Range
For Each para In ActiveDocument.Lists(1).ListParagraphs
para.Range.Select
Next para