I have made a table which auto fills using a user form. Currently, you can add new rows and edit the text within the table. I want to be able to lock the table so that you cannot edit the table at all unless you enter it through the user form. I tried the code:
Private Sub Lock_Table()
Dim NewArea As Table
Set NewArea = ActiveDocument.Tables(1)
NewArea.Locked = True
End Sub
But that came back with the error "method or data member not found"
any help would be appreciated
Thanks!
The following code will insert a table inside a new Rich Text Content Control.
Selection.Range.ContentControls.Add (wdContentControlRichText)
ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=2, NumColumns:= _
2, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
wdAutoFitFixed
That is from a recorded macro and certainly could be improved to not use the selection object. It gives a 2x2 table inside a rich text content control.
The following locks the first content control in a document.
ActiveDocument.ContentControls(1).Range _
.LockContents = True
That cannot be edited. Obviously, you would change this to False before editing in your userform.
Related
I am attempting to create an "Add Row" button in an MS Word 2016 form that will add another row to the bottom of a table that contains text content controls.
Simply adding a row doesn't include the content controls and copying a previous row will also copy over any text that has been added to those content controls, neither of which I want.
I read somewhere that it is possible to save an unpopulated row as AutoText, then insert the AutoText as a new row. I just am unable to find how to do this. I have the unpopulated row saved as AutoText, I just don't know how to add it to the bottom of the table using VBA.
Also, the form will be edit protected. The VBA code needed to unlock the form then relock it I already have. I am just leaving it off for right now while I attempt to figure this out.
I tried the below code, but keep getting a type mismatch error.
Private Sub AddInmate_Click()
ActiveDocument.Tables(2).Select
NormalTemplate.AutoTextEntries("Inmate_Row").Insert _
Where:=ActiveDocument.Tables(2).Range.Rows.Last
End Sub
Any help you all can provide is greatly appreciated.
The attempt is very close - it's trying to insert the new row "on top of" or "in" the last row. The trick is to get the table's Range then collapse it so that the target insertion point is immediately after the table. When table rows are pasted/inserted immediately after an existing table, inside the same paragraph mark, Word auotomatically incorporates them in the existing table.
Private Sub AddInmate_Click()
Dim tmpl As Word.Template
Dim rngTbl As Word.Range
Set rngTbl = ActiveDocument.Tables(2).Range
rngTbl.Collapse wdCollapseEnd
Set tmpl = NormalTemplate
tmpl.BuildingBlockEntries("Inmate_Row").Insert _
Where:=rngTbl, RichText:=True
End Sub
The approach I'd take is to use code like:
With Selection.Tables(1).Rows
'Insert an empty paragraph after our table, then replace it with a replica of the last row
With .Last.Range
.Next.InsertBefore vbCr
.Next.FormattedText = .FormattedText
End With
'Reset all content controls in the new last row
For Each CCtrl In .Last.Range.ContentControls
With CCtrl
If .Type = wdContentControlCheckBox Then .Checked = False
If .Type = wdContentControlRichText Or .Type = wdContentControlText Then .Range.Text = ""
If .Type = wdContentControlDropdownList Then .DropdownListEntries(1).Select
If .Type = wdContentControlComboBox Then .DropdownListEntries(1).Select
If .Type = wdContentControlDate Then .Range.Text = ""
End With
Next
End With
For a complete ContentControlOnExit macro implementing this in a situation analogous to yours, see: http://www.msofficeforums.com/word-vba/27809-code-add-new-row-table.html#post87989
I'm developing a spreadsheet to automatically generate quotes; this involves copying the correct diagram (a grouped Excel shape) from a sheet with a library of our possible diagrams, and pasting/inserting/[whatever will work best] that image into the VBA-assembled Word document.
So far, I am able to successfully identify, copy and paste special the correct diagram shape from Excel into Word. However, every technique I have found means that the shape either wraps text as inline or infront-- whereas I need the next portion of text to be directly aside the diagram-- thus "wdTight"
Below, you can see how I paste in the current shape. But I can't figure out how to make that shape into ".wrapFormat.Type = wdTight"
I am generally met with a series of Runtime 438 errors: object doesn't support this property or method.
I have a theory that this is because Word considers the selection to always be the blinking text cursor, and not the just pasted shape which is activated and has a hovering layout options tooltip (but that is just a theory).
Here is the code. Please help.
Sub export_excel_to_word()
Dim appWord
Dim quoteWord
Dim wordSelection
Set appWord = CreateObject("Word.Application")
appWord.Visible = True
Set quoteWord = appWord.Documents.Add
Set wordSelection = appWord.Selection
'This part works
Module1.ImagesRefresh
'Product 1 image insertion
Sheets("Quick Lookup").Shapes("QuoteProduct1Image").Copy
wordSelection.PasteSpecial Link:=False, _
DataType:=wdPasteShape, _
Placement:=wdInLine, _
DisplayAsIcon:=False
'This part does not work and is where I need help
With wordSelection
.WrapFormat.Type = wdWrapFront
End With
Try creating a variable to represent the newly pasted shape, it should be accessible by index, and should be the last index:
'Product 1 image insertion
ActiveSheet.Shapes(1).Copy
wordSelection.PasteSpecial Link:=False, _
DataType:=wdPasteShape, _
Placement:=wdInLine, _
DisplayAsIcon:=False
Dim wdShape As Word.Shape
Set wdShape = quoteWord.Shapes(quoteWord.Shapes.Count)
wdShape.WrapFormat.Type = wdWrapTight
Without using the shape variable, this might also work, but I have not tested against a document with several shapes (assuming you're adding shapes in sequence/iteration)
'Product 1 image insertion
ActiveSheet.Shapes(1).Copy
wordSelection.PasteSpecial Link:=False, _
DataType:=wdPasteShape, _
Placement:=wdInLine, _
DisplayAsIcon:=False
wordSelection.ShapeRange(1).WrapFormat.Type = wdWrapTight
If you're also inserting text (e.g., through the TypeText method of a Word.Range, try the code below. I'm not super-familar with Word automation, and the rule that you should avoid activate/select I think is less strict in Word (or has more exceptions) but as a rule of thumb, I'd still try to avoid reliance on the Selection object, and work with ranges instead.
What I'm doing here is pasting to the wordSelection.Range rather than the Selection itself. Then I do
ActiveSheet.Shapes(1).Copy
wordSelection.Range.PasteSpecial Link:=False, _
DataType:=wdPasteShape, _
Placement:=wdInLine, _
DisplayAsIcon:=False
Dim wdShape As Word.Shape
Set wdShape = quoteWord.Shapes(quoteWord.Shapes.Count)
wdShape.WrapFormat.Type = wdWrapTight
wordSelection.TypeText "some text"
I need to create a table of contents that exists at the top of page 2. In my code, I am importing a custom Title page (a building block) and also have to create the Table of Contents based on text in the document. The table of contents works/runs perfectly, it's just in the wrong location.
Sub TitlePage()
Application.Templates( _
mypath). _
BuildingBlockEntries("BuildingBlockName").Insert Where:=Selection.Range, RichText:=True
End Sub
Sub ToC()
Selection.GoTo what:=wdGoToLine, Which:=wdGoToAbsolute
Selection.EscapeKey
Selection.Range.InsertBreak
Selection.GoTo what:=wdGoToPage, Which:=wdGoToNext
Selection.EscapeKey
ActiveDocument.TablesOfContents.Add Range:=Selection.Range, RightAlignPageNumbers:= _
True, UseHeadingStyles:=True, IncludePageNumbers:=True, _
UseHyperlinks:=True, HidePageNumbersInWeb _
:=True, UseOutlineLevels:=False
End Sub
As you can see, these are two different macros that are part of a larger macro. I am using a call function in the main portion of the code to keep things organized. Is there a way to finagle the Table of contents onto page 2?
P.S. I know I've committed the sin of using the selection property. This was to navigate to the first line, then to the second page, then to escape the selection, and insert the ToC where the cursor was last.
I'm desperate.
How about something based on:
Sub ToCAndTitle()
With ActiveDocument
'Insert a Section break before existing content
.Range(0, 0).InsertBreak Type:=wdSectionBreakNextPage
.TablesOfContents.Add Range:=.Range(0, 0), RightAlignPageNumbers:=True, _
UseHeadingStyles:=True, IncludePageNumbers:=True, UseHyperlinks:=True, _
HidePageNumbersInWeb:=True, UseOutlineLevels:=False
'Insert a page break before existing content
.Range(0, 0).InsertBreak Type:=wdPageBreak
Application.Templates(mypath).BuildingBlockEntries("BuildingBlockName").Insert Where:=.Range(0, 0), RichText:=True
End With
End Sub
Inserting a Section break allows the page numbering to start after the TOC, if that's what you want.
I am writing a macro to insert a textbox containing a pre-formatted table into a Microsoft Word document, and I want it to insert the table at the current cursor location. With the current code I have, the textbox seems to be inserted at the beginning or end of the current page, instead of the cursor location.
Here is my code:
Sub InsertTable()
Dim shpTbox As Shape
Dim rngTbox As Range
Dim tblBox As Table
Set shpTbox = ActiveDocument.Shapes.addtextbox( _
Orientation:=msoTextOrientationHorizontal, _
Left:=72, Top:=50, Width:=468, Height:=220, Anchor:=Selection.Range)
shpTbox.TextFrame.TextRange.Tables.Add Range:=shpTbox.TextFrame.TextRange, NumRows:=8, NumColumns:=4, _
DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:=wdAutoFitFixed
shpTbox.TextFrame.TextRange.Tables.Item(1).Select
shpTbox.TextFrame.TextRange.Tables(1).Style = ActiveDocument.Styles("Custom Table")
Selection.InsertCaption Label:="Figure", _
Title:=". Insert Caption Here", _
Position:=wdCaptionPositionBelow
shpTbox.Line.Visible = msoFalse
shpTbox.WrapFormat.Type = wdWrapSquare
shpTbox.WrapFormat.Side = wdWrapBoth
shpTbox.TextFrame.TextRange.ParagraphFormat.Alignment = wdAlignParagraphCenter
End Sub
Is there a way to do what I want to do? Can someone explain why this doesn't do what I want it to do?
Thank you!
Word positions to the page by default. You need to tell it otherwise, and re-set the Left and Top properties afterwards. After the TextBox has been inserted specify the relative horizontal and vertical positions. For example:
shpTbox.RelativeHorizontalPosition = wdRelativeHorizontalPositionColumn
shpTbox.RelativeVerticalPosition = wdRelativeVerticalPositionLine
shpTbox.Left = 72
shpTbox.Top = 50
You may want to test some of the WdRelativeHorizontalPosition and WdRelativeVerticalPostition enumeration values to see what works best for your situation.
The problem I have got is that my corporate template set uses a SaveDate field in the footer of every word document - which is used to detail when the document was saved, which ties in with our custom document management system.
Subsequently, when users want to make a PDF of an old document, using the Save As PDF function of Office 2010, the Save Date is updated - creating a PDF of the old document, but with today's date. This is wrong. We are just trying to create a true PDF version of whatever the original document has in it.
To get around this, I am writing a macro solution which locks the fields, exports the document as a PDF and then unlocks the fields again.
I have come up against an issue where I can identify and lock all fields in the headers/footers (which is actually what I'm trying to do) but to make it more robust, need to find out a way to lock ALL FIELDS in ALL SECTIONS.
Showing you my code below, how can I identify all fields in all sections? Will this have to be done using the Index facility?
Sub CPE_CustomPDFExport()
'20-02-2013
'The function of this script is to export a PDF of the active document WITHOUT updating the fields.
'This is to create a PDF of the document as it appears - to get around Microsoft Word 2010's native behaviour.
'Route errors to the correct label
'On Error GoTo errHandler
'This sub does the following:
' -1- Locks all fields in the specified ranges of the document.
' -2- Exports the document as a PDF with various arguments.
' -3- Unlocks all fields in the specified ranges again.
' -4- Opens up the PDF file to show the user that the PDF has been generated.
'Lock document fields
Call CPE_LockFields
'Export as PDF and open afterwards
Call CPE_ExportAsPDF
'Unlock document fields
Call CPE_UnlockFields
'errHandler:
' MsgBox "Error" & Str(Err) & ": " &
End Sub
Sub CPE_LockFields()
'Update MS Word status bar
Application.StatusBar = "Saving document as PDF. Please wait..."
'Update MS Word status bar
Application.StatusBar = "Locking fields in all section of the active document..."
'Declare a variable we can use to iterate through sections of the active document
Dim docSec As section
'Loop through all document sections and lock fields in the specified ranges
For Each docSec In ActiveDocument.Sections
docSec.Footers(wdHeaderFooterFirstPage).Range.fields.Locked = True
docSec.Footers(wdHeaderFooterPrimary).Range.fields.Locked = True
docSec.Footers(wdHeaderFooterEvenPages).Range.fields.Locked = True
Next
End Sub
Sub CPE_UnlockFields()
'Update MS Word status bar
Application.StatusBar = "PDF saved to DocMan Temp. Now unlocking fields in active document. Please wait..."
'Declare a variable we can use to iterate through sections of the active document
Dim docSec As section
'Loop through all document sections and unlock fields in the specified ranges
For Each docSec In ActiveDocument.Sections
docSec.Footers(wdHeaderFooterFirstPage).Range.fields.Locked = False
docSec.Footers(wdHeaderFooterPrimary).Range.fields.Locked = False
docSec.Footers(wdHeaderFooterEvenPages).Range.fields.Locked = False
Next
End Sub
Sub CPE_ExportAsPDF()
'Update MS Word status bar
Application.StatusBar = "Saving document as PDF. Please wait..."
'Chop up the filename so that we can remove the file extension (identified by everything right of the first dot)
Dim adFilename As String
adFilename = Left(ActiveDocument.FullName, (InStrRev(ActiveDocument.FullName, ".", -1, vbTextCompare) - 1)) & ".pdf"
'Export to PDF with various arguments (here we specify file name, opening after export and exporting with bookmarks)
With ActiveDocument
.ExportAsFixedFormat outPutFileName:=adFilename, _
ExportFormat:=wdExportFormatPDF, OpenAfterExport:=True, _
OptimizeFor:=wdExportOptimizeForPrint, Range:=wdExportAllDocument, _
Item:=wdExportDocumentContent, IncludeDocProps:=True, KeepIRM:=True, _
CreateBookmarks:=wdExportCreateWordBookmarks, DocStructureTags:=True, _
BitmapMissingFonts:=True, UseISO19005_1:=False
End With
'Update MS Word status bar
Application.StatusBar = "PDF saved to DocMan Temp."
End Sub
Try something like the following to get to all fields in the document, header, footer, background and main text:
Sub LockAllFieldsInDocument(poDoc As Document, Optional pbLock As Boolean = True)
Dim oRange As Range
If Not poDoc Is Nothing Then
For Each oRange In poDoc.StoryRanges
oRange.Fields.Locked = pbLock
Next
End If
Set oRange = Nothing
End Sub
Here is another way to do it. It'll select the entire document and then lock all fields, before deselecting everything.
Sub SelectUnlink()
ActiveDocument.Range(0, 0).Select
Selection.WholeStory
Selection.Range.Fields.Unlink
Selection.End = Selection.Start
End Sub