I’m new to VBA. What I need to do is sticky labels like it is shown in picture for different projects. Such text [XXX….] in Word will be replaced by the macro in Excel which I found in internet (see below) depending on project. Text without brackets XXX… will remain the same for each sticky label. I have such Excel part of the process where source information is placed:Example
However, I have 2 special situations/issues with the text which I cannot solve:
Depending on project, I need different amount of sticky labels. Sometimes it is 30, sometimes 70. So, I would like to modify the code I have to implement a special field in Excel where I could input the exact value of the labels which I need. How can I do this?
The biggest red letter [X] will be replaced based on random sequence of A or B. So we have e.g. 70 sticky labels and random sequence is 1-A, 2-B, 3-A etc. until 70 (but it could be another sequence for next project). How can I do this?
I don’t ask for the code for that task (but if you are so kind I would really appreciate it). At least I would like to know the way I can do this in Excel VBA in order to get sticky labels in Word.
Thanks in advance.
Sub Generator()
Dim ObWord As Word.Application
Dim objDoc As Word.document
Dim file As String
Set ob1 = ActiveWorkbook.ActiveSheet
f_r = Selection.Row
stb = Selection.Column
f_c = Selection.CurrentRegion.Columns(Selection.CurrentRegion.Columns.Count).Column
path_f = ThisWorkbook.Path
file = Application.GetOpenFilename("Excel Files (*.docx;*.doc), *docx;*.doc")
If Dir(file) = Empty Then
Exit Sub
Else
Set ObjWord = CreateObject("Word.Application")
With ObjWord
.Visible = True
.Documents.Open Filename:=file
Set objDoc = .ActiveDocument
End With
With objDoc.Range
For j = 1 To f_c
isk_zn = ob1.Cells(1, j)
zamen_zn = ob1.Cells(f_r, j)
.Find.ClearFormatting
.Find.Replacement.ClearFormatting
With .Find
.Text = isk_zn
.Replacement.Text = zamen_zn
.Forward = True
.wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
.Find.Execute Replace:=2
Next j
FName = ob1.Cells(f_r, stb)
objDoc.SaveAs Filename:=path_f & "\" & FName
objDoc.Close
ObjWord.Quit
End With
Set objDoc = Nothing
Set ObjWord = Nothing
ob1.Activate
End If
End Sub
You don't need VBA to generate labels from data in Excel as this is a built-in feature.
Here is information about how to:
Create and print mailing labels for an address list in Excel
Print mailing labels (with Video)
Regardless of whether it's actually addresses that you're trying to print, the process is the same.
As for your code, I fixed indentation so it's easier to see what's going on. I'd suggest adding the line Option Explicit at the top of [every] module [always] to help "force" you to properly declare and handle your variables, objects, etc.
In your code the following variables are undeclared:
ob1, f_r, stb, f_c, path_f, file, ObjWord, j, isk_zn, zamen_zn, FName
...and at least one is misspelled (ObjWord vs ObWord).
See also:
Declaring Variables
...and Tutorials:
Home & Learn VBA Tutorial
Macro Mastery Tutorial
Microsoft's VBA Documentation
Related
I am trying to make a macro to open a word document and make track changes in accordance with column A and B.
I got this to work, but only if the document that is opened in the track changes mode "Simple Markup".
If it is in any other mode, and I have the following search sentences.
A1: al anden personer B1: alle andre mennesker
A2: anden personer B2: andre mennesker
And the text in the word document is "al anden personer".
The text will be "alle andre menneskerandre mennesker" in other world it will search in the track changes.
Therefore, I am trying to make the Word document always open in simple markup. I have tried using iteration of
ActiveWindow.View.RevisionsFilter.Markup = wdRevisionsMarkupSimple
but could not get it to work.
Hope you can help.
PS: I am fairly new to VBA so if you have any other improvement or hint the I'm all ears.
My code right now is:
Option Explicit
Const wdReplaceAll = 2
Sub FindReplace()
Dim wordApp As Object
Dim wordDoc As Object
Dim myStoryRange As Object
Dim cell As Range
Dim Find1 As String
Dim Replace1 As String
Const wdRevisionsMarkupSimple As Integer = 1
'Dim oRevision As Revision
If Not FileIsOpen("H:\Til excel replace test ark" & ".docx") Then
Set wordApp = CreateObject("Word.Application")
wordApp.Visible = True
Set wordDoc = wordApp.Documents.Open("H:\Til excel replace test ark.docx")
wordDoc.trackrevisions = True
'ActiveWindow.View.RevisionsFilter.Markup = wdRevisionsMarkupSimple cannot get it to work
Else
On Error GoTo ExitSub
End If
With Worksheets("sheet1")
For Each cell In Range("A2:A" & .Cells(.Rows.Count, "A").End(xlUp).Row)
Find1 = cell.Value
Replace1 = cell.Offset(0, 1).Value
For Each myStoryRange In wordDoc.StoryRanges
With myStoryRange.Find
.MatchCase = True
.matchwholeword = True
.Text = Find1
.Forward = True
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.Replacement.Text = Replace1
.Execute Replace:=wdReplaceAll
End With
Next myStoryRange
Next cell
End With
Exit Sub
ExitSub:
MsgBox "Luk word document før du benytter denne macro"
End Sub
Public Function FileIsOpen(FullFilePath As String) As Boolean
Dim ff As Long
On Error Resume Next
ff = FreeFile()
Open FullFilePath For Input Lock Read As #ff
Close ff
FileIsOpen = (Err.Number <> 0)
On Error GoTo 0
End Function
Your issue is a result of your use of late binding.
When using late binding you cannot use the enums or constants from the Word object library, e.g. wdRevisionsMarkupSimple, as Excel doesn't know what those represent. You either have to declare those constants yourself or use their underlying values.
So to activate revisions with simple markup your code needs to be:
ActiveWindow.View.RevisionsFilter.Markup = 1 'wdRevisionsMarkupSimple
EDIT: I also missed something else obvious - Excel also has ActiveWindow in its object model. When writing code across applications you need to be absolutely scrupulous in specifying which application/object the line of code refers to. In this case it should be:
WordApp.ActiveWindow.View.RevisionsFilter.Markup = 1 'wdRevisionsMarkupSimple
You can avoid these errors by adding Option Explicit at the top of the code module. This will prevent your code from compiling when you have undeclared variables. To add this automatically open the VBE and go to Tools | Options. In the Options dialog ensure that Require Variable Declaration is checked.
Would you please help me to select the whole paragraph beneath a given heading in a word file and import its content to an excel file through VBA?
The heading is always named 'Notes' in the word file and is the heading 4 when I use the Go to command to reach it.
I tried to use the content.find property with the word.application object but it copies the entire document.
I also tried to reach the requested title with the GoTo method with the following paraeters: what:=wdGoToHeading, which:=wdGoToAbsolute, Count:=4, but it is not accepted by the method and outputs an error message when compiled.
Sub ImportWordTables()
'Imports a table from Word document
Dim applWord As Object
Dim notes As String
Dim wdDoc As Object
Dim wdDocName As String
Dim wdFileName As Variant
...
Set applWord = CreateObject("Word.Application")
applWord.Visible = True
applWord.WindowState = 1
wdFileName = Application.GetOpenFilename("Word files (*.doc*),*.doc*", , _
"Browse for file containing table to be imported")
If wdFileName = False Then Exit Sub '(user cancelled import file browser)
Application.Goto (ActiveWorkbook.Sheets("Sheet1").Range("A1"))
Set wdDoc = applWord.Documents.Open(wdFileName)
I tried:
applWord.ActiveDocument.Range.Selection.Goto what:=wdGoToHeading, which:=wdGoToAbsolute, Count:=4
And:
With applWord.ActiveDocument.Content.Find
.ClearFormatting
.Text = "Notes"
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
With .Parent
.Select
.Copy
End With
applWord.ActiveDocument.Range.Selection.Copy
Thanks a lot for your help and have a nice day !
You're on the right track with Content.Find...
When you use Find, remember to also use .Execute, otherwise, nothing will happen. It's like clicking the OK button in a dialog box, after setting the properties.
Generally, it's better to use a dedicated Range object with Find that can be manipulated. When Find is run, the range or selection on which it is executed will change to the "found" content. So Selection.Find would have worked for you (as long as you execute). But ActiveDocument.Content cannot because it can't change. That's why a dedicated Range object is needed.
Extending the found content: Word has a number of Move methods for ranges and selections. For this, I'd use MoveEnd (for details see the language reference).
The following code snippet, based on code in the question, illustrates these points.
Dim rngFind As Object
Set wdDoc = applWord.Documents.Open(wdFileName)
Set rngFind = wdDoc.content
With rngFind.Find
.ClearFormatting
.Text = "Notes"
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Format = True
If .Execute Then
rngFind.MoveEnd wdParagraph, 2
rngFind.Copy
End If
End With
Thanks again for your help.
I achieved to get something into the clipboard with the following:
Dim applWord As Object
Dim rngFind As Word.Range
Set rngFind = ActiveDocument.Content
With rngFind.Find
.ClearFormatting
.Text = "Notes"
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
End With
rngFind.MoveEnd wdParagraph, 2
rngFind.Select
rngFind.Copy
There are many code lines next to this to change the layout, add some formulas, etc., but I do not put them for clarity purpose.
So, it works !
Next difficulty is with
rngFind.MoveEnd wdParagraph, 2
In fact, the content of the 'Notes' heading in my word file is a numbering list, so it is like:
Notes
1) first point
2) ...
3) ...
4) ...
With an undefined number of elements.
Is there a command I can use to be sure to catch the whole paragraph?
Yesterday, I tried to find a VBA command which would allow to collapse the heading, before copying it. The equivalent of right clicking next to it, 'Expand/collapse', then 'collapse heading'. I did not find anything like this, and I am not sure it is the best way to achieve what I would like.
So, if you still have bit of time to advise me, you would be warmly welcome :-)
Thanks and have a nice day !
I'm building a code that will use a template (a Word doc embedded in Excel) and will find and replace certain words in the template using the inputs from Excel. I have successfully coded the opening of the template, find and replace in the template.
But after that, when I check the embedded Word doc in Excel, the replaced words were saved. I don't want to override the contents of the template but every time I run my code, it automatically saves the changes made during the find and replace. I just want it to find and replace, then save a copy to my local folder.
I'm using late binding as there is a limitation in the version of Excel that our team is using.
I don't know if the function of the below code is the one causing the changes to be saved in the embedded Word doc.
.Execute Replace:=2 'wdReplaceAll
Here is the my full code:
Sub Button1_Click()
Application.ScreenUpdating = False
Set WDApp = CreateObject("Word.Application")
WDApp.Visible = True
Set WDDoc = Sheets("Sheet1").OLEObjects("Template_112225")
WDDoc.Verb Verb:=xlOpen
WDApp.Selection.WholeStory
Call SplitCell
Call Find("<Part Num>", Sheets("Sheet2").Cells(8, 4).Value)
Call Find("<Dataset>", Sheets("Sheet2").Cells(7, 3).Value)
Call Find("<Letter>", Sheets("Sheet2").Cells(8, 5).Value)
Set WDDoc = Nothing
Set WDApp = Nothing
Set Rng = Nothing
End Sub
Sub Find(Find_Value As String, New_Value As String)
With WDApp.Selection.Find
.Text = Find_Value
.Replacement.Text = New_Value
.Forward = True
.Wrap = 1 'wdFindContinue
.Execute Replace:=2 'wdReplaceAll
End With
End Sub
Sub SplitCell()
Dim txt As String
Dim i As Integer
Dim NumberLetter As Variant
txt = Sheets("Sheet2").Cells(8, 3).Value
NumberLetter = Split(txt, "/")
For i = 0 To UBound(NumberLetter)
Cells(8, i + 4).Value = NumberLetter(i)
Next i
End Sub
Also is it possible to have a code that will make the Save As dialog box appear? So the user can have a choice on where to save the modified copy.
Good Morning!
I am creating a tool to format many word documents with the same settings, and am working on setting all document body data to the column count specified, and the margins as specified. When run, this code works, but does not set the left/ right margins appropriately. The code should set each of them to the same value.
When run it seems to be variable. For instance, if I choose 0.3; the left margin will end of as 0.2 and the right will be 0.4. To make it a little weirder, if I manually go into the custom margin settings in MS Word, it states it is at the appropriate numbers (0.3) even when the margin bar on the page is not set there.
Has anyone worked with margins via vb to know if this is a setting issue, or if there is a more accurate way? I think it may have something to do with the column spacing .SpaceAfter = InchesToPoints(frmWordEdit.txtColumnSpacing), but I am unsure.
Any help is appreciated!
Sub AddRemoveWatermark(strReplaceText As String)
'Word Variables
Dim wrdApplication As Word.Application
Dim wrdDocument As Word.Document
Dim wrdSection As Word.section
Dim wrdSelection As Word.Selection
Dim wrdHeader As Word.HeaderFooter
Dim rngHeader As Word.Range
Dim rngFooter As Word.HeaderFooter
Dim spShape As Word.Shape
Dim strDocumentName As String
Dim strPath As String
Dim strBBPath As String
Dim lngCount As Long
' Open the file dialog
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = True
.Show
Set wrdApplication = New Word.Application
' Display paths of each file selected
For lngCount = 1 To .SelectedItems.Count
strPath = .SelectedItems(lngCount)
Set wrdDocument = wrdApplication.Documents.Open(strPath)
strDocumentName = wrdDocument.FullName 'Record the document name
wrdApplication.Templates.LoadBuildingBlocks
wrdApplication.Visible = True
'Document Layout
If frmWordEdit.chkDocumentLayout.Value = True Then
'Change Columns
If frmWordEdit.chkColumns = True Then
With wrdDocument.PageSetup.TextColumns
.SetCount NumColumns:=frmWordEdit.txtColumns
'.Add EvenlySpaced:=True
'.Width = InchesToPoints(3)
'.SpaceAfter = InchesToPoints(0.3)
End With
Dim i As Integer
If frmWordEdit.txtColumns > 1 Then
For i = 1 To frmWordEdit.txtColumns - 1
With wrdDocument.PageSetup.TextColumns(i)
'.Width = InchesToPoints(4)
.SpaceAfter = InchesToPoints(frmWordEdit.txtColumnSpacing)
End With
Next
End If
End If
'Change Margins
If frmWordEdit.chkMargins = True Then
With wrdDocument.PageSetup
.LeftMargin = wrdApplication.InchesToPoints(frmWordEdit.txtMLeftRight)
.RightMargin = wrdApplication.InchesToPoints(frmWordEdit.txtMLeftRight)
.TopMargin = wrdApplication.InchesToPoints(frmWordEdit.txtMTop)
.BottomMargin = wrdApplication.InchesToPoints(frmWordEdit.txtMBottom)
End With
End If
End If
'Document Design
If frmWordEdit.chkDocumentDesign.Value = True Then
If frmWordEdit.chkMHeader = True Then
With wrdDocument.PageSetup
.HeaderDistance = wrdApplication.InchesToPoints(frmWordEdit.txtMHeader)
End With
End If
If frmWordEdit.chkMFooter = True Then
With wrdDocument.PageSetup
.FooterDistance = wrdApplication.InchesToPoints(frmWordEdit.txtMFooter)
End With
End If
End If
End Sub
This is the part of your code which sets the margins.
With wrdDocument.PageSetup
.LeftMargin = wrdApplication.InchesToPoints(frmWordEdit.txtMLeftRight)
.RightMargin = wrdApplication.InchesToPoints(frmWordEdit.txtMLeftRight)
.TopMargin = wrdApplication.InchesToPoints(frmWordEdit.txtMTop)
.BottomMargin = wrdApplication.InchesToPoints(frmWordEdit.txtMBottom)
End With
I find no fault with the syntax (except that you don't need to specify wrdApplication unless you run the code from another application, perhaps Excel). Since the code appears without fault errors must have their origin in the reference to frmWordEdit. I suggest that you run this code with plain numbers, expressed in points, and see if you still get the same result.
frmWordEdit.txtMLeftRight would appear to be a Textbox. Since you don't specify which property you are referring to it must be the default which is the Value property. The Value property of a Textbox holds a string which you feed into the InchesToPoints function. That function takes a single, if I'm not mistaken - anyway, a numeric value. Therefore I suspect that the string isn't correctly translated. Try something like InchesToPoints(Val(frmWordEdit.txtMLeftRight)).
Thank you for taking the time to read my request. I have tried using a few answers on this site and I am not getting what I want. (I tried this: Word VBA how to select text between two substrings and assign to variable?)
I am trying to select a number that is ALWAYS between the two same words. It is between "Account No.:" and "IMPORTANT" (yes in all caps, unsure if caps/ no-caps matters for denoting it).
I am creating a macro where I open a word document with say 200 pages. I want to open and save EACH PAGE as it's own pdf with a specific name. I have gotten the code to run where I open and save as PDF. What I want to do, is with in that code, have something that finds the text between "Account No.:" and "IMPORTANT", selects it and copies it. This text is an account number.
Then, when I go to save the file, I want it to paste the account number as the file name. Or have a reference that when it finds the account number it assigns it to a variable. I am new to VBA, so if you can please be descriptive, and put instructions in laymans terms. THANK YOU!
My macro:
Sub CutePDFWriter()
Dim FName, FPath, username, LoanNo As String
Dim wordapp As Word.Application
Dim wordDoc As Word.Document
Dim i As Integer
Dim rngParagraphs As Range
'open doc and export as a pdf
Set wordapp = CreateObject("word.Application")
Set wordDoc = wordapp.Documents.Open("G:\test.doc")
For i = 1 To wordDoc.BuiltinDocumentProperties("Number of Pages")
**Here is where I want to add the “Find and Select” code**
'set variable strings
FPath = "G:\Excel Doc Tests\"
FName = "___**Here is where I want the acct nbr to go_______"** & i & ""
wordDoc.ExportAsFixedFormat FPath & FName & "-escrtax", ExportFormat:=wdExportFormatPDF, Range:=wdExportFromTo, From:=i, To:=i
Next i
'empty word doc objects
wordDoc.Close (False)
wordapp.Quit
End Sub
I added a comment to the question at that link which makes his code work. But I spent time on this: (tested with "blah blah Account No.:123-456IMPORTANT blah blah"):
Option Explicit
Sub Sub1()
Dim i&, FName$ ' I presume
Dim i1&, i2&, s1$, rngDoc As Range
Selection.HomeKey wdStory ' ?
i1 = getPoint("Account No.:", 1) ' get start
i2 = getPoint("IMPORTANT", 2) ' get end
Set rngDoc = ActiveDocument.Range(i1, i2)
s1 = rngDoc.Text
FName = "Prefix" & s1 & "Postfix" & Str$(i)
Stop ' and hover over FName
End Sub
Function getPoint&(sText$, iStart&) ' 1 for start, 2 for end
With Selection.Find
.Text = sText
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = True
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.Execute
End With
If iStart = 1 Then
getPoint = Selection.End
Else
getPoint = Selection.Start
End If
End Function