I am trying to format a Word document with the help of VBA.
If I supply a page number, it should clear all tabstops for that particular page only.
I have the code to clear all the tabstops but could not modify it for a specific page.
ActiveDocument.Paragraphs.TabStops.ClearAll
Try this:
Dim pnum As Integer
pnum = InputBox("Enter page number")
ActiveDocument.ActiveWindow.Panes(1).Pages(pnum).Rectangles(1).Range.Paragraphs.TabStops.ClearAll
Remember that pages are a fairly arbitrary concept in a document, so it might not be so easy to identify the content you want to by a page number. Elements that span multiple pages (like tables) can also cause confusion.
Related
I uncheck "Allow row to break across pages" for a table's properties So, the table is shown on a new page to ensure that all the content is on one page, this works fine. But Word generates a blank space before the page break, I need to replace it with some text for a legal reason. I can't use a watermark or shapes because un Oracle BI Publisher only prints it on PDF and I need to export it to a docx.
The data is dynamic, so sometimes the text before the table and the text inside the table may change.
Current Version https://imgur.com/a/FTx0q
I need some like this https://imgur.com/a/ySitL
MS Office support told me that it can't be done with Word...
Maybe with VBA code?
Update
Thanks Cindy for your help.
I have a table into another table many paragraphs, checkbox etc and they are fitting on a new page. It's working.
I understand there isn't a page break.
It's Paragraph mark.
But what I need to do is insert a kind of mark, a text like XXXX,-----------, Instead of leaving "free space",
It's a requirement not change the font size or another text format.
For a legal requirement, some paragraph must fit on a new page and "blank spaces" replaced by a kind of mark.
I can't hard code it because in several cases not all the paragraphs or section in a page will be shown and I don't know by default when a new page is needed.
I am available to use macros or anything.
What you could do is insert a page-size table into a textbox in the page header and format the body text with a white background. The table will thus be hidden behind any text on the page, but not otherwise (provided you don't pad unused space with empty paragraphs, etc.).
I need to analyze text of my Word document, and create bookmarks on range of text my analyzer has detected (almost like a grammar checker).
I don't want use Find() utility, because my needs are too specific.
Explanations
For that,
1/ Retrieve Document plain text
I Retrieve Plain text of the main story of my document :
String plainText = ActiveDocument.Range().Text;
2/ Analyze plain text and get results
I send it to my analyzer tool which return a collection of marker with position :
For example, if I wanted to detected the pattern "my pattern" in the document text, analyzer could return a marker as { pattern : "my marker", start: 5, end : 14 }, where "start" and "end" are the character indexes of the pattern in the plain text sent.
3/ Display results in Document
I create bookmark from theses markers
For previously example, it woold be :
// init a new range and collapse it
Word.Range range = activeDocument.Range(); range.Collapse(WdCollapseStart);
// move character-by-character in the "formatted" text
range.MoveStart(WdUnits.Character, Marker.start ); # Marker.start=5
//set length (end)
range.setRange(range.Start,range.Start+(Marker.End-Marker.Start)); #Marker.end=14
4/ Results
4.1 Global Result
Everything is OK when Document Main Story Contains Text, links, lists, titles :
Ranges are well positionned, Plain Text indexes correlate with formatted text indexes.
4.2 Arrays Issue
When a document contains an array, Ranges are bad positionned a few characters : Plain Text indexes correlate not exactly with formatted text indexes.
I found the reason of this issue (It was explained in others forums) : this is due to non printing char(7), which is a cell delimiter added in plain text. We can handle these chars to calculate position range and everything is OK !
4.3 Issue for Content Controls, Table of contents, Sections and others
When a document contains theses elements, Ranges are also bad positionned a few characters.
Others non printing appears in plain text but I don't understand what it means and how deal with to calculate position range.
By displaying Word element markers with "Developer ribbon > creation mode", we see 2 markers per elements : shifting plain text indexes by 2*elements resolve issues. It's seems OK.
4.4 Issue with Endpaper
I don't know how we says "page de garde" (french) in english, I think it's "endpaper" : this is the first page with specific header, footer and content controls :)
When a document contains an Endpaper, Ranges are also bad positionned a few characters.
But this time, there are not non printing marker in the plain text.
Other info, when I display word element markers with "Developer ribbon > creation mode", I see endpaper markers.
Questions
How detect Endpaper in Word Document Range ?
How understand Plain Text indexes don't always correlate with formatted text indexes, in function of Word document elements which contains ?
XML nodes manipulation would be a more reliable alternative for that? If yes, could you give me good examples to manage bookmars or others in current document with XML Api ?
Others ressources
I found similar issues :
Correlate Range.Text to Range.Start and Range.End
http://www.vbaexpress.com/forum/showthread.php?36710-Strange-character-on-table-range-text
I hope my explanations are clear and you can help me to understand what is wrong or show me a best way to do that ?
Thanks, really.
It's not really pretty but you can try to remove the unwanted characters by Regex. For example to remove the \a letters (it has code 7):
string j = new string(new char[] { (char)7 });
plainText = Regex.Replace(plainText,string.Format("[{0}]", j), "");
Now you have to identify the other 'evil' characters and add them to the char array. If it works you will get a string whose length corresponds with the number of Characters in your document. Probably you have to adapt this code by experimenting. (I was not sure which language you are using - I supposed C#.)
Update
Another idea (if it is applicable to your analyzer tool):
Break your problem down to single paragraphs:
foreach(Word.Paragraph pg in activeDocument.Paragraphs)
{
Word.Range range = pg.Range();
string text = range.Text;
// your stuff here
}
With this paragraph range objects and the contained text strings you do the same as you tried to do with the whole document object and its text - just paragraph by paragraph. All these paragraphs are 'addressable' by ranges and Move operations as you already do it. I suppose that the problematic characters are outside or at the end of the paragraphs so they don't influence the character counting inside these paragraphs.
As I can't reproduce what you call endpaper I can't validate it. Besides I don't know if special text ranges as page headers and tables of content are covered by paragraphs. But at least you can reduce your problem to smaller ranges. I think it is worth trying.
I am using VBA on Word and trying to do a task with a simple description:
Make document content fit on 1 or 2 pages, without leaving a lot of empty space on the last page.
To do that, I started with one simple step:
Determine total document content height.
(to later manipulate font size and line spacing according to my needs)
Problem is:
ActiveDocument.Content.Paragraphs lists all paragraphs with no regards to hierarchy. If I have a table in the content, all its contents will be listed, so I can't just use that to infer document content height.
I would like to work over the document structure tree, like
doc.header
doc.contents
paragraph1
table1
cell1
t1c1p1
cell2
t1c2p1
t1c2p2
paragraph2
paragraph3
doc.footer
And iterate only over the direct children of the content root to get their heights.
But I am having a hard time finding a way to do that. Can anyone give me some help?
I am fairly new to VBA (Word 2010) and I'm unsure if something I'd like to do is even possible in the way that I want to do it, or if I need to investigate completely different avenues. I want to be able to print ranges (or items) that are not currently enumerated as part of either wdPrintOutRange or wdPrintOutItem. Is it possible to define a member of a wd enumeration?
As an example, I'd like to be able to print comments by a particular user. wdPrintComments is a member of the wdPrintOutItem enumeration, but, I only want comments that have an Initial value of JQC. Can I define a wdPrintCommentsJQC constant? My code is reasonably simple; I have a userform that lets the user pick some settings (comments by user, endnotes only, etc.) and a Run button whose Click event should generate a PrintOut method with the proper attributes. Am I on the wrong track?
(If it matters, the Initial values will be known to me as I write the code. I have a discrete list.)
No, it's not possible to add a constant to a predefined enumeration type.
However, one possible way to do this would be to build a string of page numbers which contain the items you wish to print, open the print dialog in the "dialogs" collection, and set it to print a specified range, andinsert the string containing the list of pages (separate them with commas). Finally, execute the .show method of the print dialog to show it to the user and give them the opportunity to set any other items and click the "ok" button. I've done something very similar when I needed to print a specific chapter of a long document, and so I had to specify the "from" section and page and the "to" section and page for the user. Below I just show how to specify a list of pages instead of the ".form" and "to" I was using:
With Dialogs(wdDialogFilePrint)
.Range = wdPrintRangeOfPages
.Pages = "3,5,7-11"
.show
end with
I'm not sure how you want to print the comments (or other elements), but you could create another document and insert what you want to print on this document.
According to what you want, you could insert them as they were (comments, footnotes, etc) or as plain text, or any other format.
I'd like to be able to create a page element which I can feed text and it will form itself into the preferred layout. For instance:
{MACRO DocumentIntro("Introduction to Business Studies", "FP015", "Teachers' Guide")}
with that as a field, the output should be a line, the first two strings a certain size and font, centred, another line and then the third string fonted, sized and centred.
I know that's sort of TeX-like and perhaps beyond the scope of VBA, but if anyone's got any idea how it might be possible, please tell!
EDIT:
Ok, if I put the required information into Keyword, as part of the document properties, with some kind of unique separator, then that gets that info in, and the info will be unique to each document. Next one puts a bookmark where the stuff is going to be displayed. Then one creates an AutoOpen macro that goes to that bookmark, pulls the relevants out of the keywords, and forms the text appropriately into the bookmark's .Selection.
Is that feasible?
You're certainly on the right track here for a coding solution. However, there is a simpler way with no code - this is the type of scenario that Content Controls in Word 2007 were built for and with Fields/Properties, you can bind to content controls (CC). These CC can hold styles (like centered, bold, etc.). No VBA required.
The very easiest thing to do is to pick 3 built-in document properties that you will always want these to be. For example, "Title" could be your first string, "Subject" your second string and "Keywords" your third. Then, just go to the Insert ribbon, Quick Parts, Document Properties and insert, place and format those how you like. Then go to Word's start button (the orb thingy) and then under Prepare choose Properties. Here you can type, for example "Introduction to Business Studies", into the Title box and then just deselect it somehow (like click in another box). The Content Control for Title will be filled in automatically with your text.
If you want to use this for multiple files, just create this file as a .dotx (after CC insertion/placement/formatting and before updating the Document Properties' text). Then every time all you'll have to do is set these three properties with each new file.
Well, yes, it did turn out to be feasible.
Sub autoopen()
Dim sKeywords As String
sKeywords = ActiveDocument.BuiltInDocumentProperties(4)
ActiveDocument.Bookmarks("foo").Select
Selection.Text = sKeywords
End Sub
Okay, I have some filling out to do, but at least the guts of it are there.