Find and replace placeholders in Word with values from Excel











up vote
1
down vote

favorite












I'm new at this and need assistance with shortening/streamlining the 2 pieces of code that is repeated three times each (this is a shortened version as these pieces of code is repeated many more times).



Sub CreateWordDocTest()

Dim wApp As Word.Application
Dim wDoc As Word.Document
Dim myStoryRange As Word.Range
Dim InsName, InsNumber, CurrentYear, Industry, AnalysisToolPath, AnalysisToolName, FileNameFragment2, TodaysDate, TemplatePath As String

If RADType = "Full" Then
TemplatePath = Sheets("Metadata").Range("D8").Value
NotificationWhenDone = "Full RAD done"
TodaysDate = Now() 'Variable called TodaysDate would now contain the current system date and time
Else
TemplatePath = Sheets("Metadata").Range("D6").Value
NotificationWhenDone = "Summary RAD done"
TodaysDate = Now()
End If

Set wApp = CreateObject("Word.Application")
wApp.Visible = True 'Creates an instance of Word an makes it visible
Set wDoc = wApp.Documents.Open(TemplatePath, False) 'Opens the chosen full or summary RAD template

With wDoc 'Use the With statement to not repeat wDoc many times

'Start at the beginning of the Word document

.Application.Selection.HomeKey Unit:=wdStory 'Moves the selection to the beginning of the current story

InsName = Sheets("Parameters").Range("D4").Value
InsNumber = Sheets("Parameters").Range("D5").Value
CurrentYear = Sheets("Parameters").Range("D6").Value
Industry = Sheets("Parameters").Range("D7").Value
AnalysisToolPath = Sheets("Metadata").Range("D2").Value
FileNameFragment2 = InsNumber & " - " & InsName & " " & CurrentYear & ".xlsm"
AnalysisToolName = AnalysisToolPath & FileNameFragment2

'Write insurer name

For Each myStoryRange In ActiveDocument.StoryRanges
With myStoryRange.Find
.Text = "<<InsurerName>>" 'Find the exact text in the Word document
.Replacement.Text = InsName 'Replace this text with the insurername as defined
.Wrap = wdFindContinue 'The find operation continues when the beginning or end of the search range is reached
.Execute Replace:=wdReplaceAll 'Finds all occurences and executes the replacement
End With

Next myStoryRange
.Application.Selection.EndOf 'Selects until the end of the document

'Write insurer class
For Each myStoryRange In ActiveDocument.StoryRanges
With myStoryRange.Find
.Text = "<<InsurerClass>>"
.Replacement.Text = Industry
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With

Next myStoryRange
.Application.Selection.EndOf

'Write financial year
For Each myStoryRange In ActiveDocument.StoryRanges
With myStoryRange.Find
.Text = "<<CurrentYear>>"
.Replacement.Text = CurrentYear
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With

Next myStoryRange
.Application.Selection.EndOf

'Write significant classes
For Each myStoryRange In ActiveDocument.StoryRanges
With myStoryRange.Find
.Text = "<<SignificantClasses>>"
.Replacement.Text = SignificantclassesTxt
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
Next myStoryRange
.Application.Selection.EndOf

'Write insurer number
.Application.Selection.Find.Text = "<<InsurerNumber>>"
.Application.Selection.Find.Execute
.Application.Selection = Sheets("Parameters").Range("D5").Value
.Application.Selection.EndOf

'Write analyst name
.Application.Selection.Find.Text = "<<AnalystName>>"
.Application.Selection.Find.Execute
.Application.Selection = UserFullName
.Application.Selection.EndOf

'Write RiBS Wording
.Application.Selection.Find.Text = "<<RiBSWording>>"
.Application.Selection.Find.Execute
.Application.Selection = SignificantclassesRiBSTxt
.Application.Selection.EndOf

End With

End Sub









share|improve this question














bumped to the homepage by Community 14 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.



















    up vote
    1
    down vote

    favorite












    I'm new at this and need assistance with shortening/streamlining the 2 pieces of code that is repeated three times each (this is a shortened version as these pieces of code is repeated many more times).



    Sub CreateWordDocTest()

    Dim wApp As Word.Application
    Dim wDoc As Word.Document
    Dim myStoryRange As Word.Range
    Dim InsName, InsNumber, CurrentYear, Industry, AnalysisToolPath, AnalysisToolName, FileNameFragment2, TodaysDate, TemplatePath As String

    If RADType = "Full" Then
    TemplatePath = Sheets("Metadata").Range("D8").Value
    NotificationWhenDone = "Full RAD done"
    TodaysDate = Now() 'Variable called TodaysDate would now contain the current system date and time
    Else
    TemplatePath = Sheets("Metadata").Range("D6").Value
    NotificationWhenDone = "Summary RAD done"
    TodaysDate = Now()
    End If

    Set wApp = CreateObject("Word.Application")
    wApp.Visible = True 'Creates an instance of Word an makes it visible
    Set wDoc = wApp.Documents.Open(TemplatePath, False) 'Opens the chosen full or summary RAD template

    With wDoc 'Use the With statement to not repeat wDoc many times

    'Start at the beginning of the Word document

    .Application.Selection.HomeKey Unit:=wdStory 'Moves the selection to the beginning of the current story

    InsName = Sheets("Parameters").Range("D4").Value
    InsNumber = Sheets("Parameters").Range("D5").Value
    CurrentYear = Sheets("Parameters").Range("D6").Value
    Industry = Sheets("Parameters").Range("D7").Value
    AnalysisToolPath = Sheets("Metadata").Range("D2").Value
    FileNameFragment2 = InsNumber & " - " & InsName & " " & CurrentYear & ".xlsm"
    AnalysisToolName = AnalysisToolPath & FileNameFragment2

    'Write insurer name

    For Each myStoryRange In ActiveDocument.StoryRanges
    With myStoryRange.Find
    .Text = "<<InsurerName>>" 'Find the exact text in the Word document
    .Replacement.Text = InsName 'Replace this text with the insurername as defined
    .Wrap = wdFindContinue 'The find operation continues when the beginning or end of the search range is reached
    .Execute Replace:=wdReplaceAll 'Finds all occurences and executes the replacement
    End With

    Next myStoryRange
    .Application.Selection.EndOf 'Selects until the end of the document

    'Write insurer class
    For Each myStoryRange In ActiveDocument.StoryRanges
    With myStoryRange.Find
    .Text = "<<InsurerClass>>"
    .Replacement.Text = Industry
    .Wrap = wdFindContinue
    .Execute Replace:=wdReplaceAll
    End With

    Next myStoryRange
    .Application.Selection.EndOf

    'Write financial year
    For Each myStoryRange In ActiveDocument.StoryRanges
    With myStoryRange.Find
    .Text = "<<CurrentYear>>"
    .Replacement.Text = CurrentYear
    .Wrap = wdFindContinue
    .Execute Replace:=wdReplaceAll
    End With

    Next myStoryRange
    .Application.Selection.EndOf

    'Write significant classes
    For Each myStoryRange In ActiveDocument.StoryRanges
    With myStoryRange.Find
    .Text = "<<SignificantClasses>>"
    .Replacement.Text = SignificantclassesTxt
    .Wrap = wdFindContinue
    .Execute Replace:=wdReplaceAll
    End With
    Next myStoryRange
    .Application.Selection.EndOf

    'Write insurer number
    .Application.Selection.Find.Text = "<<InsurerNumber>>"
    .Application.Selection.Find.Execute
    .Application.Selection = Sheets("Parameters").Range("D5").Value
    .Application.Selection.EndOf

    'Write analyst name
    .Application.Selection.Find.Text = "<<AnalystName>>"
    .Application.Selection.Find.Execute
    .Application.Selection = UserFullName
    .Application.Selection.EndOf

    'Write RiBS Wording
    .Application.Selection.Find.Text = "<<RiBSWording>>"
    .Application.Selection.Find.Execute
    .Application.Selection = SignificantclassesRiBSTxt
    .Application.Selection.EndOf

    End With

    End Sub









    share|improve this question














    bumped to the homepage by Community 14 mins ago


    This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.

















      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I'm new at this and need assistance with shortening/streamlining the 2 pieces of code that is repeated three times each (this is a shortened version as these pieces of code is repeated many more times).



      Sub CreateWordDocTest()

      Dim wApp As Word.Application
      Dim wDoc As Word.Document
      Dim myStoryRange As Word.Range
      Dim InsName, InsNumber, CurrentYear, Industry, AnalysisToolPath, AnalysisToolName, FileNameFragment2, TodaysDate, TemplatePath As String

      If RADType = "Full" Then
      TemplatePath = Sheets("Metadata").Range("D8").Value
      NotificationWhenDone = "Full RAD done"
      TodaysDate = Now() 'Variable called TodaysDate would now contain the current system date and time
      Else
      TemplatePath = Sheets("Metadata").Range("D6").Value
      NotificationWhenDone = "Summary RAD done"
      TodaysDate = Now()
      End If

      Set wApp = CreateObject("Word.Application")
      wApp.Visible = True 'Creates an instance of Word an makes it visible
      Set wDoc = wApp.Documents.Open(TemplatePath, False) 'Opens the chosen full or summary RAD template

      With wDoc 'Use the With statement to not repeat wDoc many times

      'Start at the beginning of the Word document

      .Application.Selection.HomeKey Unit:=wdStory 'Moves the selection to the beginning of the current story

      InsName = Sheets("Parameters").Range("D4").Value
      InsNumber = Sheets("Parameters").Range("D5").Value
      CurrentYear = Sheets("Parameters").Range("D6").Value
      Industry = Sheets("Parameters").Range("D7").Value
      AnalysisToolPath = Sheets("Metadata").Range("D2").Value
      FileNameFragment2 = InsNumber & " - " & InsName & " " & CurrentYear & ".xlsm"
      AnalysisToolName = AnalysisToolPath & FileNameFragment2

      'Write insurer name

      For Each myStoryRange In ActiveDocument.StoryRanges
      With myStoryRange.Find
      .Text = "<<InsurerName>>" 'Find the exact text in the Word document
      .Replacement.Text = InsName 'Replace this text with the insurername as defined
      .Wrap = wdFindContinue 'The find operation continues when the beginning or end of the search range is reached
      .Execute Replace:=wdReplaceAll 'Finds all occurences and executes the replacement
      End With

      Next myStoryRange
      .Application.Selection.EndOf 'Selects until the end of the document

      'Write insurer class
      For Each myStoryRange In ActiveDocument.StoryRanges
      With myStoryRange.Find
      .Text = "<<InsurerClass>>"
      .Replacement.Text = Industry
      .Wrap = wdFindContinue
      .Execute Replace:=wdReplaceAll
      End With

      Next myStoryRange
      .Application.Selection.EndOf

      'Write financial year
      For Each myStoryRange In ActiveDocument.StoryRanges
      With myStoryRange.Find
      .Text = "<<CurrentYear>>"
      .Replacement.Text = CurrentYear
      .Wrap = wdFindContinue
      .Execute Replace:=wdReplaceAll
      End With

      Next myStoryRange
      .Application.Selection.EndOf

      'Write significant classes
      For Each myStoryRange In ActiveDocument.StoryRanges
      With myStoryRange.Find
      .Text = "<<SignificantClasses>>"
      .Replacement.Text = SignificantclassesTxt
      .Wrap = wdFindContinue
      .Execute Replace:=wdReplaceAll
      End With
      Next myStoryRange
      .Application.Selection.EndOf

      'Write insurer number
      .Application.Selection.Find.Text = "<<InsurerNumber>>"
      .Application.Selection.Find.Execute
      .Application.Selection = Sheets("Parameters").Range("D5").Value
      .Application.Selection.EndOf

      'Write analyst name
      .Application.Selection.Find.Text = "<<AnalystName>>"
      .Application.Selection.Find.Execute
      .Application.Selection = UserFullName
      .Application.Selection.EndOf

      'Write RiBS Wording
      .Application.Selection.Find.Text = "<<RiBSWording>>"
      .Application.Selection.Find.Execute
      .Application.Selection = SignificantclassesRiBSTxt
      .Application.Selection.EndOf

      End With

      End Sub









      share|improve this question













      I'm new at this and need assistance with shortening/streamlining the 2 pieces of code that is repeated three times each (this is a shortened version as these pieces of code is repeated many more times).



      Sub CreateWordDocTest()

      Dim wApp As Word.Application
      Dim wDoc As Word.Document
      Dim myStoryRange As Word.Range
      Dim InsName, InsNumber, CurrentYear, Industry, AnalysisToolPath, AnalysisToolName, FileNameFragment2, TodaysDate, TemplatePath As String

      If RADType = "Full" Then
      TemplatePath = Sheets("Metadata").Range("D8").Value
      NotificationWhenDone = "Full RAD done"
      TodaysDate = Now() 'Variable called TodaysDate would now contain the current system date and time
      Else
      TemplatePath = Sheets("Metadata").Range("D6").Value
      NotificationWhenDone = "Summary RAD done"
      TodaysDate = Now()
      End If

      Set wApp = CreateObject("Word.Application")
      wApp.Visible = True 'Creates an instance of Word an makes it visible
      Set wDoc = wApp.Documents.Open(TemplatePath, False) 'Opens the chosen full or summary RAD template

      With wDoc 'Use the With statement to not repeat wDoc many times

      'Start at the beginning of the Word document

      .Application.Selection.HomeKey Unit:=wdStory 'Moves the selection to the beginning of the current story

      InsName = Sheets("Parameters").Range("D4").Value
      InsNumber = Sheets("Parameters").Range("D5").Value
      CurrentYear = Sheets("Parameters").Range("D6").Value
      Industry = Sheets("Parameters").Range("D7").Value
      AnalysisToolPath = Sheets("Metadata").Range("D2").Value
      FileNameFragment2 = InsNumber & " - " & InsName & " " & CurrentYear & ".xlsm"
      AnalysisToolName = AnalysisToolPath & FileNameFragment2

      'Write insurer name

      For Each myStoryRange In ActiveDocument.StoryRanges
      With myStoryRange.Find
      .Text = "<<InsurerName>>" 'Find the exact text in the Word document
      .Replacement.Text = InsName 'Replace this text with the insurername as defined
      .Wrap = wdFindContinue 'The find operation continues when the beginning or end of the search range is reached
      .Execute Replace:=wdReplaceAll 'Finds all occurences and executes the replacement
      End With

      Next myStoryRange
      .Application.Selection.EndOf 'Selects until the end of the document

      'Write insurer class
      For Each myStoryRange In ActiveDocument.StoryRanges
      With myStoryRange.Find
      .Text = "<<InsurerClass>>"
      .Replacement.Text = Industry
      .Wrap = wdFindContinue
      .Execute Replace:=wdReplaceAll
      End With

      Next myStoryRange
      .Application.Selection.EndOf

      'Write financial year
      For Each myStoryRange In ActiveDocument.StoryRanges
      With myStoryRange.Find
      .Text = "<<CurrentYear>>"
      .Replacement.Text = CurrentYear
      .Wrap = wdFindContinue
      .Execute Replace:=wdReplaceAll
      End With

      Next myStoryRange
      .Application.Selection.EndOf

      'Write significant classes
      For Each myStoryRange In ActiveDocument.StoryRanges
      With myStoryRange.Find
      .Text = "<<SignificantClasses>>"
      .Replacement.Text = SignificantclassesTxt
      .Wrap = wdFindContinue
      .Execute Replace:=wdReplaceAll
      End With
      Next myStoryRange
      .Application.Selection.EndOf

      'Write insurer number
      .Application.Selection.Find.Text = "<<InsurerNumber>>"
      .Application.Selection.Find.Execute
      .Application.Selection = Sheets("Parameters").Range("D5").Value
      .Application.Selection.EndOf

      'Write analyst name
      .Application.Selection.Find.Text = "<<AnalystName>>"
      .Application.Selection.Find.Execute
      .Application.Selection = UserFullName
      .Application.Selection.EndOf

      'Write RiBS Wording
      .Application.Selection.Find.Text = "<<RiBSWording>>"
      .Application.Selection.Find.Execute
      .Application.Selection = SignificantclassesRiBSTxt
      .Application.Selection.EndOf

      End With

      End Sub






      performance beginner vba






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jun 22 at 9:44









      MRK

      61




      61





      bumped to the homepage by Community 14 mins ago


      This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







      bumped to the homepage by Community 14 mins ago


      This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
























          3 Answers
          3






          active

          oldest

          votes

















          up vote
          0
          down vote













          To streamline this and remove the abundant code duplication, you could extract the two distinct parts you repeat into Subs taking parameters and then call those.



          Private Sub ReplacePlaceholderInDocument(document As Word.Document, placeholder As String, replacement As String)


          You could also get all placeholder values in another function and put them as key value pairs into a Scripting.Dictionary and call your new sub in a loop over the the dictionary keys.



          There are a few more things that could be improved to enhance the maintainability of the code:



          The code would really benefit from a better separation of concern. According to the single responsibility principle, each unit of program should be concerned with only one responsibility. Your sub seems to combine the responsibilities of choosing the template, getting the template, getting the replacement values (including getting the reference sheet and its name) and replacing the values. Each of these could go into its own sub or function after which the main sub only coordinates the use of the new subs and functions.



          Next, I see that you are referring to the ActiveDocument, which is a bad idea most of the time. This will be different depending on which Word document currently has focus. It is usually better to use an explicit document, unless the currently active document is really what you need.



          You also take values from the reference sheets from explicit cell addresses. That is rather fragile: any layout change can make the code invalid. A better alternative is to use named ranges in Excel. These can be referred to using their name.



          You also seem to take values from variables defined outside the sub, like UserFullName. Unless this is a method to be called as a makro, you might consider to make these parameters of the sub. That would make the sub more self contained.



          Finally, it is a good practice to state accessibilities exicitly. The sub is currently defined without one, which means that it is implicitly Public.



          There are probably a few more improvements one could make, but I will leave it with this.






          share|improve this answer






























            up vote
            0
            down vote













            You aren't giving a Type to most of these variables -




            Dim InsName, InsNumber, CurrentYear, Industry, AnalysisToolPath, AnalysisToolName, FileNameFragment2, TodaysDate, TemplatePath As String



            In fact, only TemplatePath has a type. The rest are all variants. You need to explicitly type all of them e.g.



            Dim InsName as String, InsNumber as String, CurrentYear as String, ...


            When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch



            When you don't define your variable, VBA will declare it as a Variant, which are objects:




            Performance. A variable you declare with the Object type is flexible
            enough to contain a reference to any object. However, when you invoke
            a method or property on such a variable, you always incur late binding
            (at run time). To force early binding (at compile time) and better
            performance, declare the variable with a specific class name, or cast
            it to the specific data type.




            This also includes not defining RADType, NotificationWhenDone etc





            You have a bunch of comments. Comments - "code tell you how, comments tell you why". The code should speak for itself, if it needs a comment, it might need to be made more clear. If not, the comment should describe why you're doing something rather than how you're doing it. Here are a few reasons to avoid comments all together.





            Dim wApp As Word.Application
            Set wApp = CreateObject("Word.Application")


            Are you using early binding or late binding, because you're doing both. Either



            Dim wApp As Object
            Set wApp = CreateObject("Word.Application")


            or



            Dim wApp As Word.Application
            Set wApp = New Word.Application




            As you know, When you repeat code you can most likely benefit from refactoring it. Throw it into a function or method and use the function each time you need the code - it will be a lot cleaner.



            As addressed by the other answer something like



            Public Sub CreateDocument(ByVal templateSheet As Worksheet, ByVal parameterSheet As Worksheet)


            And you pass the target worksheets to it. Or maybe you pass the target word document, or whatever changes each time you need to call the sub.



            Speaking of the worksheets - Worksheets have a CodeName property - View Properties window (F4) and the (Name) field (the one at the top) can be used as the worksheet name. This way you can avoid Sheets("mySheet") and instead just use mySheet.





            I don't really have the time right now, but it seems you do the exact same thing over and over? I don't see anything changing - all the ranges are hard-coded.






            share|improve this answer






























              up vote
              0
              down vote













              Here's a way to apply some of the tricks the other answers mentioned:



              You don't need the TodaysDate line twice, do you?



              If RADType = "Full" Then
              TemplatePath = Sheets("Metadata").Range("D8").Value
              NotificationWhenDone = "Full RAD done"
              Else
              TemplatePath = Sheets("Metadata").Range("D6").Value
              NotificationWhenDone = "Summary RAD done"
              End If
              TodaysDate = Now() 'Variable called TodaysDate would now contain the current system date and time


              Also, why do multiple loops?



              'Write insurer name

              For Each myStoryRange In ActiveDocument.StoryRanges
              With myStoryRange.Find
              .Text = "<<InsurerName>>" 'Find the exact text in the Word document
              .Replacement.Text = InsName 'Replace this text with the insurername as defined
              .Wrap = wdFindContinue 'The find operation continues when the beginning or end of the search range is reached
              .Execute Replace:=wdReplaceAll 'Finds all occurences and executes the replacement
              End With

              'DONT NEED THIS: Next myStoryRange
              .Application.Selection.EndOf 'Selects until the end of the document

              'Write insurer class
              'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
              With myStoryRange.Find
              .Text = "<<InsurerClass>>"
              .Replacement.Text = Industry
              .Wrap = wdFindContinue
              .Execute Replace:=wdReplaceAll
              End With

              'DONT NEED THIS: Next myStoryRange
              .Application.Selection.EndOf

              'Write financial year
              'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
              With myStoryRange.Find
              .Text = "<<CurrentYear>>"
              .Replacement.Text = CurrentYear
              .Wrap = wdFindContinue
              .Execute Replace:=wdReplaceAll
              End With

              'DONT NEED THIS: Next myStoryRange
              .Application.Selection.EndOf

              'Write significant classes
              'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
              With myStoryRange.Find
              .Text = "<<SignificantClasses>>"
              .Replacement.Text = SignificantclassesTxt
              .Wrap = wdFindContinue
              .Execute Replace:=wdReplaceAll
              End With
              Next myStoryRange
              .Application.Selection.EndOf





              share|improve this answer





















                Your Answer





                StackExchange.ifUsing("editor", function () {
                return StackExchange.using("mathjaxEditing", function () {
                StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
                StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
                });
                });
                }, "mathjax-editing");

                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "196"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                convertImagesToLinks: false,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: null,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                 

                draft saved


                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f197052%2ffind-and-replace-placeholders-in-word-with-values-from-excel%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                3 Answers
                3






                active

                oldest

                votes








                3 Answers
                3






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes








                up vote
                0
                down vote













                To streamline this and remove the abundant code duplication, you could extract the two distinct parts you repeat into Subs taking parameters and then call those.



                Private Sub ReplacePlaceholderInDocument(document As Word.Document, placeholder As String, replacement As String)


                You could also get all placeholder values in another function and put them as key value pairs into a Scripting.Dictionary and call your new sub in a loop over the the dictionary keys.



                There are a few more things that could be improved to enhance the maintainability of the code:



                The code would really benefit from a better separation of concern. According to the single responsibility principle, each unit of program should be concerned with only one responsibility. Your sub seems to combine the responsibilities of choosing the template, getting the template, getting the replacement values (including getting the reference sheet and its name) and replacing the values. Each of these could go into its own sub or function after which the main sub only coordinates the use of the new subs and functions.



                Next, I see that you are referring to the ActiveDocument, which is a bad idea most of the time. This will be different depending on which Word document currently has focus. It is usually better to use an explicit document, unless the currently active document is really what you need.



                You also take values from the reference sheets from explicit cell addresses. That is rather fragile: any layout change can make the code invalid. A better alternative is to use named ranges in Excel. These can be referred to using their name.



                You also seem to take values from variables defined outside the sub, like UserFullName. Unless this is a method to be called as a makro, you might consider to make these parameters of the sub. That would make the sub more self contained.



                Finally, it is a good practice to state accessibilities exicitly. The sub is currently defined without one, which means that it is implicitly Public.



                There are probably a few more improvements one could make, but I will leave it with this.






                share|improve this answer



























                  up vote
                  0
                  down vote













                  To streamline this and remove the abundant code duplication, you could extract the two distinct parts you repeat into Subs taking parameters and then call those.



                  Private Sub ReplacePlaceholderInDocument(document As Word.Document, placeholder As String, replacement As String)


                  You could also get all placeholder values in another function and put them as key value pairs into a Scripting.Dictionary and call your new sub in a loop over the the dictionary keys.



                  There are a few more things that could be improved to enhance the maintainability of the code:



                  The code would really benefit from a better separation of concern. According to the single responsibility principle, each unit of program should be concerned with only one responsibility. Your sub seems to combine the responsibilities of choosing the template, getting the template, getting the replacement values (including getting the reference sheet and its name) and replacing the values. Each of these could go into its own sub or function after which the main sub only coordinates the use of the new subs and functions.



                  Next, I see that you are referring to the ActiveDocument, which is a bad idea most of the time. This will be different depending on which Word document currently has focus. It is usually better to use an explicit document, unless the currently active document is really what you need.



                  You also take values from the reference sheets from explicit cell addresses. That is rather fragile: any layout change can make the code invalid. A better alternative is to use named ranges in Excel. These can be referred to using their name.



                  You also seem to take values from variables defined outside the sub, like UserFullName. Unless this is a method to be called as a makro, you might consider to make these parameters of the sub. That would make the sub more self contained.



                  Finally, it is a good practice to state accessibilities exicitly. The sub is currently defined without one, which means that it is implicitly Public.



                  There are probably a few more improvements one could make, but I will leave it with this.






                  share|improve this answer

























                    up vote
                    0
                    down vote










                    up vote
                    0
                    down vote









                    To streamline this and remove the abundant code duplication, you could extract the two distinct parts you repeat into Subs taking parameters and then call those.



                    Private Sub ReplacePlaceholderInDocument(document As Word.Document, placeholder As String, replacement As String)


                    You could also get all placeholder values in another function and put them as key value pairs into a Scripting.Dictionary and call your new sub in a loop over the the dictionary keys.



                    There are a few more things that could be improved to enhance the maintainability of the code:



                    The code would really benefit from a better separation of concern. According to the single responsibility principle, each unit of program should be concerned with only one responsibility. Your sub seems to combine the responsibilities of choosing the template, getting the template, getting the replacement values (including getting the reference sheet and its name) and replacing the values. Each of these could go into its own sub or function after which the main sub only coordinates the use of the new subs and functions.



                    Next, I see that you are referring to the ActiveDocument, which is a bad idea most of the time. This will be different depending on which Word document currently has focus. It is usually better to use an explicit document, unless the currently active document is really what you need.



                    You also take values from the reference sheets from explicit cell addresses. That is rather fragile: any layout change can make the code invalid. A better alternative is to use named ranges in Excel. These can be referred to using their name.



                    You also seem to take values from variables defined outside the sub, like UserFullName. Unless this is a method to be called as a makro, you might consider to make these parameters of the sub. That would make the sub more self contained.



                    Finally, it is a good practice to state accessibilities exicitly. The sub is currently defined without one, which means that it is implicitly Public.



                    There are probably a few more improvements one could make, but I will leave it with this.






                    share|improve this answer














                    To streamline this and remove the abundant code duplication, you could extract the two distinct parts you repeat into Subs taking parameters and then call those.



                    Private Sub ReplacePlaceholderInDocument(document As Word.Document, placeholder As String, replacement As String)


                    You could also get all placeholder values in another function and put them as key value pairs into a Scripting.Dictionary and call your new sub in a loop over the the dictionary keys.



                    There are a few more things that could be improved to enhance the maintainability of the code:



                    The code would really benefit from a better separation of concern. According to the single responsibility principle, each unit of program should be concerned with only one responsibility. Your sub seems to combine the responsibilities of choosing the template, getting the template, getting the replacement values (including getting the reference sheet and its name) and replacing the values. Each of these could go into its own sub or function after which the main sub only coordinates the use of the new subs and functions.



                    Next, I see that you are referring to the ActiveDocument, which is a bad idea most of the time. This will be different depending on which Word document currently has focus. It is usually better to use an explicit document, unless the currently active document is really what you need.



                    You also take values from the reference sheets from explicit cell addresses. That is rather fragile: any layout change can make the code invalid. A better alternative is to use named ranges in Excel. These can be referred to using their name.



                    You also seem to take values from variables defined outside the sub, like UserFullName. Unless this is a method to be called as a makro, you might consider to make these parameters of the sub. That would make the sub more self contained.



                    Finally, it is a good practice to state accessibilities exicitly. The sub is currently defined without one, which means that it is implicitly Public.



                    There are probably a few more improvements one could make, but I will leave it with this.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jun 22 at 11:39

























                    answered Jun 22 at 10:30









                    M.Doerner

                    97638




                    97638
























                        up vote
                        0
                        down vote













                        You aren't giving a Type to most of these variables -




                        Dim InsName, InsNumber, CurrentYear, Industry, AnalysisToolPath, AnalysisToolName, FileNameFragment2, TodaysDate, TemplatePath As String



                        In fact, only TemplatePath has a type. The rest are all variants. You need to explicitly type all of them e.g.



                        Dim InsName as String, InsNumber as String, CurrentYear as String, ...


                        When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch



                        When you don't define your variable, VBA will declare it as a Variant, which are objects:




                        Performance. A variable you declare with the Object type is flexible
                        enough to contain a reference to any object. However, when you invoke
                        a method or property on such a variable, you always incur late binding
                        (at run time). To force early binding (at compile time) and better
                        performance, declare the variable with a specific class name, or cast
                        it to the specific data type.




                        This also includes not defining RADType, NotificationWhenDone etc





                        You have a bunch of comments. Comments - "code tell you how, comments tell you why". The code should speak for itself, if it needs a comment, it might need to be made more clear. If not, the comment should describe why you're doing something rather than how you're doing it. Here are a few reasons to avoid comments all together.





                        Dim wApp As Word.Application
                        Set wApp = CreateObject("Word.Application")


                        Are you using early binding or late binding, because you're doing both. Either



                        Dim wApp As Object
                        Set wApp = CreateObject("Word.Application")


                        or



                        Dim wApp As Word.Application
                        Set wApp = New Word.Application




                        As you know, When you repeat code you can most likely benefit from refactoring it. Throw it into a function or method and use the function each time you need the code - it will be a lot cleaner.



                        As addressed by the other answer something like



                        Public Sub CreateDocument(ByVal templateSheet As Worksheet, ByVal parameterSheet As Worksheet)


                        And you pass the target worksheets to it. Or maybe you pass the target word document, or whatever changes each time you need to call the sub.



                        Speaking of the worksheets - Worksheets have a CodeName property - View Properties window (F4) and the (Name) field (the one at the top) can be used as the worksheet name. This way you can avoid Sheets("mySheet") and instead just use mySheet.





                        I don't really have the time right now, but it seems you do the exact same thing over and over? I don't see anything changing - all the ranges are hard-coded.






                        share|improve this answer



























                          up vote
                          0
                          down vote













                          You aren't giving a Type to most of these variables -




                          Dim InsName, InsNumber, CurrentYear, Industry, AnalysisToolPath, AnalysisToolName, FileNameFragment2, TodaysDate, TemplatePath As String



                          In fact, only TemplatePath has a type. The rest are all variants. You need to explicitly type all of them e.g.



                          Dim InsName as String, InsNumber as String, CurrentYear as String, ...


                          When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch



                          When you don't define your variable, VBA will declare it as a Variant, which are objects:




                          Performance. A variable you declare with the Object type is flexible
                          enough to contain a reference to any object. However, when you invoke
                          a method or property on such a variable, you always incur late binding
                          (at run time). To force early binding (at compile time) and better
                          performance, declare the variable with a specific class name, or cast
                          it to the specific data type.




                          This also includes not defining RADType, NotificationWhenDone etc





                          You have a bunch of comments. Comments - "code tell you how, comments tell you why". The code should speak for itself, if it needs a comment, it might need to be made more clear. If not, the comment should describe why you're doing something rather than how you're doing it. Here are a few reasons to avoid comments all together.





                          Dim wApp As Word.Application
                          Set wApp = CreateObject("Word.Application")


                          Are you using early binding or late binding, because you're doing both. Either



                          Dim wApp As Object
                          Set wApp = CreateObject("Word.Application")


                          or



                          Dim wApp As Word.Application
                          Set wApp = New Word.Application




                          As you know, When you repeat code you can most likely benefit from refactoring it. Throw it into a function or method and use the function each time you need the code - it will be a lot cleaner.



                          As addressed by the other answer something like



                          Public Sub CreateDocument(ByVal templateSheet As Worksheet, ByVal parameterSheet As Worksheet)


                          And you pass the target worksheets to it. Or maybe you pass the target word document, or whatever changes each time you need to call the sub.



                          Speaking of the worksheets - Worksheets have a CodeName property - View Properties window (F4) and the (Name) field (the one at the top) can be used as the worksheet name. This way you can avoid Sheets("mySheet") and instead just use mySheet.





                          I don't really have the time right now, but it seems you do the exact same thing over and over? I don't see anything changing - all the ranges are hard-coded.






                          share|improve this answer

























                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            You aren't giving a Type to most of these variables -




                            Dim InsName, InsNumber, CurrentYear, Industry, AnalysisToolPath, AnalysisToolName, FileNameFragment2, TodaysDate, TemplatePath As String



                            In fact, only TemplatePath has a type. The rest are all variants. You need to explicitly type all of them e.g.



                            Dim InsName as String, InsNumber as String, CurrentYear as String, ...


                            When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch



                            When you don't define your variable, VBA will declare it as a Variant, which are objects:




                            Performance. A variable you declare with the Object type is flexible
                            enough to contain a reference to any object. However, when you invoke
                            a method or property on such a variable, you always incur late binding
                            (at run time). To force early binding (at compile time) and better
                            performance, declare the variable with a specific class name, or cast
                            it to the specific data type.




                            This also includes not defining RADType, NotificationWhenDone etc





                            You have a bunch of comments. Comments - "code tell you how, comments tell you why". The code should speak for itself, if it needs a comment, it might need to be made more clear. If not, the comment should describe why you're doing something rather than how you're doing it. Here are a few reasons to avoid comments all together.





                            Dim wApp As Word.Application
                            Set wApp = CreateObject("Word.Application")


                            Are you using early binding or late binding, because you're doing both. Either



                            Dim wApp As Object
                            Set wApp = CreateObject("Word.Application")


                            or



                            Dim wApp As Word.Application
                            Set wApp = New Word.Application




                            As you know, When you repeat code you can most likely benefit from refactoring it. Throw it into a function or method and use the function each time you need the code - it will be a lot cleaner.



                            As addressed by the other answer something like



                            Public Sub CreateDocument(ByVal templateSheet As Worksheet, ByVal parameterSheet As Worksheet)


                            And you pass the target worksheets to it. Or maybe you pass the target word document, or whatever changes each time you need to call the sub.



                            Speaking of the worksheets - Worksheets have a CodeName property - View Properties window (F4) and the (Name) field (the one at the top) can be used as the worksheet name. This way you can avoid Sheets("mySheet") and instead just use mySheet.





                            I don't really have the time right now, but it seems you do the exact same thing over and over? I don't see anything changing - all the ranges are hard-coded.






                            share|improve this answer














                            You aren't giving a Type to most of these variables -




                            Dim InsName, InsNumber, CurrentYear, Industry, AnalysisToolPath, AnalysisToolName, FileNameFragment2, TodaysDate, TemplatePath As String



                            In fact, only TemplatePath has a type. The rest are all variants. You need to explicitly type all of them e.g.



                            Dim InsName as String, InsNumber as String, CurrentYear as String, ...


                            When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch



                            When you don't define your variable, VBA will declare it as a Variant, which are objects:




                            Performance. A variable you declare with the Object type is flexible
                            enough to contain a reference to any object. However, when you invoke
                            a method or property on such a variable, you always incur late binding
                            (at run time). To force early binding (at compile time) and better
                            performance, declare the variable with a specific class name, or cast
                            it to the specific data type.




                            This also includes not defining RADType, NotificationWhenDone etc





                            You have a bunch of comments. Comments - "code tell you how, comments tell you why". The code should speak for itself, if it needs a comment, it might need to be made more clear. If not, the comment should describe why you're doing something rather than how you're doing it. Here are a few reasons to avoid comments all together.





                            Dim wApp As Word.Application
                            Set wApp = CreateObject("Word.Application")


                            Are you using early binding or late binding, because you're doing both. Either



                            Dim wApp As Object
                            Set wApp = CreateObject("Word.Application")


                            or



                            Dim wApp As Word.Application
                            Set wApp = New Word.Application




                            As you know, When you repeat code you can most likely benefit from refactoring it. Throw it into a function or method and use the function each time you need the code - it will be a lot cleaner.



                            As addressed by the other answer something like



                            Public Sub CreateDocument(ByVal templateSheet As Worksheet, ByVal parameterSheet As Worksheet)


                            And you pass the target worksheets to it. Or maybe you pass the target word document, or whatever changes each time you need to call the sub.



                            Speaking of the worksheets - Worksheets have a CodeName property - View Properties window (F4) and the (Name) field (the one at the top) can be used as the worksheet name. This way you can avoid Sheets("mySheet") and instead just use mySheet.





                            I don't really have the time right now, but it seems you do the exact same thing over and over? I don't see anything changing - all the ranges are hard-coded.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Jun 23 at 4:54

























                            answered Jun 23 at 0:01









                            Raystafarian

                            5,7841047




                            5,7841047






















                                up vote
                                0
                                down vote













                                Here's a way to apply some of the tricks the other answers mentioned:



                                You don't need the TodaysDate line twice, do you?



                                If RADType = "Full" Then
                                TemplatePath = Sheets("Metadata").Range("D8").Value
                                NotificationWhenDone = "Full RAD done"
                                Else
                                TemplatePath = Sheets("Metadata").Range("D6").Value
                                NotificationWhenDone = "Summary RAD done"
                                End If
                                TodaysDate = Now() 'Variable called TodaysDate would now contain the current system date and time


                                Also, why do multiple loops?



                                'Write insurer name

                                For Each myStoryRange In ActiveDocument.StoryRanges
                                With myStoryRange.Find
                                .Text = "<<InsurerName>>" 'Find the exact text in the Word document
                                .Replacement.Text = InsName 'Replace this text with the insurername as defined
                                .Wrap = wdFindContinue 'The find operation continues when the beginning or end of the search range is reached
                                .Execute Replace:=wdReplaceAll 'Finds all occurences and executes the replacement
                                End With

                                'DONT NEED THIS: Next myStoryRange
                                .Application.Selection.EndOf 'Selects until the end of the document

                                'Write insurer class
                                'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                With myStoryRange.Find
                                .Text = "<<InsurerClass>>"
                                .Replacement.Text = Industry
                                .Wrap = wdFindContinue
                                .Execute Replace:=wdReplaceAll
                                End With

                                'DONT NEED THIS: Next myStoryRange
                                .Application.Selection.EndOf

                                'Write financial year
                                'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                With myStoryRange.Find
                                .Text = "<<CurrentYear>>"
                                .Replacement.Text = CurrentYear
                                .Wrap = wdFindContinue
                                .Execute Replace:=wdReplaceAll
                                End With

                                'DONT NEED THIS: Next myStoryRange
                                .Application.Selection.EndOf

                                'Write significant classes
                                'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                With myStoryRange.Find
                                .Text = "<<SignificantClasses>>"
                                .Replacement.Text = SignificantclassesTxt
                                .Wrap = wdFindContinue
                                .Execute Replace:=wdReplaceAll
                                End With
                                Next myStoryRange
                                .Application.Selection.EndOf





                                share|improve this answer

























                                  up vote
                                  0
                                  down vote













                                  Here's a way to apply some of the tricks the other answers mentioned:



                                  You don't need the TodaysDate line twice, do you?



                                  If RADType = "Full" Then
                                  TemplatePath = Sheets("Metadata").Range("D8").Value
                                  NotificationWhenDone = "Full RAD done"
                                  Else
                                  TemplatePath = Sheets("Metadata").Range("D6").Value
                                  NotificationWhenDone = "Summary RAD done"
                                  End If
                                  TodaysDate = Now() 'Variable called TodaysDate would now contain the current system date and time


                                  Also, why do multiple loops?



                                  'Write insurer name

                                  For Each myStoryRange In ActiveDocument.StoryRanges
                                  With myStoryRange.Find
                                  .Text = "<<InsurerName>>" 'Find the exact text in the Word document
                                  .Replacement.Text = InsName 'Replace this text with the insurername as defined
                                  .Wrap = wdFindContinue 'The find operation continues when the beginning or end of the search range is reached
                                  .Execute Replace:=wdReplaceAll 'Finds all occurences and executes the replacement
                                  End With

                                  'DONT NEED THIS: Next myStoryRange
                                  .Application.Selection.EndOf 'Selects until the end of the document

                                  'Write insurer class
                                  'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                  With myStoryRange.Find
                                  .Text = "<<InsurerClass>>"
                                  .Replacement.Text = Industry
                                  .Wrap = wdFindContinue
                                  .Execute Replace:=wdReplaceAll
                                  End With

                                  'DONT NEED THIS: Next myStoryRange
                                  .Application.Selection.EndOf

                                  'Write financial year
                                  'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                  With myStoryRange.Find
                                  .Text = "<<CurrentYear>>"
                                  .Replacement.Text = CurrentYear
                                  .Wrap = wdFindContinue
                                  .Execute Replace:=wdReplaceAll
                                  End With

                                  'DONT NEED THIS: Next myStoryRange
                                  .Application.Selection.EndOf

                                  'Write significant classes
                                  'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                  With myStoryRange.Find
                                  .Text = "<<SignificantClasses>>"
                                  .Replacement.Text = SignificantclassesTxt
                                  .Wrap = wdFindContinue
                                  .Execute Replace:=wdReplaceAll
                                  End With
                                  Next myStoryRange
                                  .Application.Selection.EndOf





                                  share|improve this answer























                                    up vote
                                    0
                                    down vote










                                    up vote
                                    0
                                    down vote









                                    Here's a way to apply some of the tricks the other answers mentioned:



                                    You don't need the TodaysDate line twice, do you?



                                    If RADType = "Full" Then
                                    TemplatePath = Sheets("Metadata").Range("D8").Value
                                    NotificationWhenDone = "Full RAD done"
                                    Else
                                    TemplatePath = Sheets("Metadata").Range("D6").Value
                                    NotificationWhenDone = "Summary RAD done"
                                    End If
                                    TodaysDate = Now() 'Variable called TodaysDate would now contain the current system date and time


                                    Also, why do multiple loops?



                                    'Write insurer name

                                    For Each myStoryRange In ActiveDocument.StoryRanges
                                    With myStoryRange.Find
                                    .Text = "<<InsurerName>>" 'Find the exact text in the Word document
                                    .Replacement.Text = InsName 'Replace this text with the insurername as defined
                                    .Wrap = wdFindContinue 'The find operation continues when the beginning or end of the search range is reached
                                    .Execute Replace:=wdReplaceAll 'Finds all occurences and executes the replacement
                                    End With

                                    'DONT NEED THIS: Next myStoryRange
                                    .Application.Selection.EndOf 'Selects until the end of the document

                                    'Write insurer class
                                    'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                    With myStoryRange.Find
                                    .Text = "<<InsurerClass>>"
                                    .Replacement.Text = Industry
                                    .Wrap = wdFindContinue
                                    .Execute Replace:=wdReplaceAll
                                    End With

                                    'DONT NEED THIS: Next myStoryRange
                                    .Application.Selection.EndOf

                                    'Write financial year
                                    'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                    With myStoryRange.Find
                                    .Text = "<<CurrentYear>>"
                                    .Replacement.Text = CurrentYear
                                    .Wrap = wdFindContinue
                                    .Execute Replace:=wdReplaceAll
                                    End With

                                    'DONT NEED THIS: Next myStoryRange
                                    .Application.Selection.EndOf

                                    'Write significant classes
                                    'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                    With myStoryRange.Find
                                    .Text = "<<SignificantClasses>>"
                                    .Replacement.Text = SignificantclassesTxt
                                    .Wrap = wdFindContinue
                                    .Execute Replace:=wdReplaceAll
                                    End With
                                    Next myStoryRange
                                    .Application.Selection.EndOf





                                    share|improve this answer












                                    Here's a way to apply some of the tricks the other answers mentioned:



                                    You don't need the TodaysDate line twice, do you?



                                    If RADType = "Full" Then
                                    TemplatePath = Sheets("Metadata").Range("D8").Value
                                    NotificationWhenDone = "Full RAD done"
                                    Else
                                    TemplatePath = Sheets("Metadata").Range("D6").Value
                                    NotificationWhenDone = "Summary RAD done"
                                    End If
                                    TodaysDate = Now() 'Variable called TodaysDate would now contain the current system date and time


                                    Also, why do multiple loops?



                                    'Write insurer name

                                    For Each myStoryRange In ActiveDocument.StoryRanges
                                    With myStoryRange.Find
                                    .Text = "<<InsurerName>>" 'Find the exact text in the Word document
                                    .Replacement.Text = InsName 'Replace this text with the insurername as defined
                                    .Wrap = wdFindContinue 'The find operation continues when the beginning or end of the search range is reached
                                    .Execute Replace:=wdReplaceAll 'Finds all occurences and executes the replacement
                                    End With

                                    'DONT NEED THIS: Next myStoryRange
                                    .Application.Selection.EndOf 'Selects until the end of the document

                                    'Write insurer class
                                    'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                    With myStoryRange.Find
                                    .Text = "<<InsurerClass>>"
                                    .Replacement.Text = Industry
                                    .Wrap = wdFindContinue
                                    .Execute Replace:=wdReplaceAll
                                    End With

                                    'DONT NEED THIS: Next myStoryRange
                                    .Application.Selection.EndOf

                                    'Write financial year
                                    'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                    With myStoryRange.Find
                                    .Text = "<<CurrentYear>>"
                                    .Replacement.Text = CurrentYear
                                    .Wrap = wdFindContinue
                                    .Execute Replace:=wdReplaceAll
                                    End With

                                    'DONT NEED THIS: Next myStoryRange
                                    .Application.Selection.EndOf

                                    'Write significant classes
                                    'DONT NEED THIS: For Each myStoryRange In ActiveDocument.StoryRanges
                                    With myStoryRange.Find
                                    .Text = "<<SignificantClasses>>"
                                    .Replacement.Text = SignificantclassesTxt
                                    .Wrap = wdFindContinue
                                    .Execute Replace:=wdReplaceAll
                                    End With
                                    Next myStoryRange
                                    .Application.Selection.EndOf






                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Jun 27 at 0:18









                                    Shawn V. Wilson

                                    1514




                                    1514






























                                         

                                        draft saved


                                        draft discarded



















































                                         


                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function () {
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f197052%2ffind-and-replace-placeholders-in-word-with-values-from-excel%23new-answer', 'question_page');
                                        }
                                        );

                                        Post as a guest















                                        Required, but never shown





















































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown

































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown







                                        Popular posts from this blog

                                        Costa Masnaga

                                        Fotorealismo

                                        Sidney Franklin