View Full Version : Solved: Using Subroutine to efficiently call multiple entries from building blocks.dotx
bstephens
07-26-2010, 10:39 AM
Ok, so I think this is probably a basic question, but struggling to figure it out, I am assuming it has to do with passing variables.
I got the following code from Graham Mayor's website (as seen here: http://www.gmayor.com/word_vba_examples.htm) and it works great to insert a "Building Block" I created called "Front of Contract 1"
Sub InsertMyBuildingBlock()
    Dim strText As String
    Dim oTemplate As Template
    Dim oAddin As AddIn
    Dim bFound As Boolean
    Dim i As Long
'Define the required building block entry
strText = "Front of Contract 1"
'Set the found flag default to False
bFound = False
'If the entry has still not been found
'finally check the Building Blocks.dotx template
If bFound = False Then
     Templates.LoadBuildingBlocks
     For Each oTemplate In Templates
          If oTemplate.Name = "Building Blocks.dotx" Then Exit For
     Next
     For i = 1 To Templates(oTemplate.FullName).BuildingBlockEntries.Count
          If Templates(oTemplate.FullName).BuildingBlockEntries(i).Name = strText Then
               Templates(oTemplate.FullName).BuildingBlockEntries(strText).Insert _
                 Where:=Selection.Range
               'set the found flag to true
               bFound = True
               'Clean up and stop looking
               Set oTemplate = Nothing
               Exit Sub
          End If
     Next i
End If
'All sources have been checked and the entry is still not found
If bFound = False Then 'so tell the user.
     MsgBox "Entry not found, please reinstall Building Block.dotx or check with computer administrator", vbInformation, "Building Block " _
       & Chr(145) & strText & Chr(146)
End If
End Sub 
My question is how do I use a subroutine (is that the right term?) to efficiently call InsertMyBuildingBlock except that it will insert "Front of Contract 2" without rewriting all that code?
Asked (I hope) more clearly, how do I create an efficient function that will reuse the code in InsertMyBuildingBlock, except use a different "strText"?
I appreciate all the input I have received from you guys thus far!
Best,
Brian
fumei
07-26-2010, 11:47 AM
Indeed, you pass it in as a paramter, like so:
Option Explicit
Sub InsertMyBuildingBlock(strBB_Name As String)
Dim oTemplate As Template
Dim oAddin As AddIn
Dim bFound As Boolean
Dim i As Long
 
 'Set the found flag default to False
bFound = False
 
 'If the entry has still not been found
 'finally check the Building Blocks.dotx template
If bFound = False Then
     
    Templates.LoadBuildingBlocks
    For Each oTemplate In Templates
        If oTemplate.Name = "Building Blocks.dotx" Then Exit For
    Next
    For i = 1 To Templates(oTemplate.FullName).BuildingBlockEntries.Count
        If Templates(oTemplate.FullName).BuildingBlockEntries(i).Name = strBB_Name Then
            Templates(oTemplate.FullName).BuildingBlockEntries(strBB_Name).Insert _
            Where:=Selection.Range
             'set the found flag to true
            bFound = True
             'Clean up and stop looking
            Set oTemplate = Nothing
            Exit Sub
        End If
    Next i
End If
 
 'All sources have been checked and the entry is still not found
If bFound = False Then 'so tell the user.
    MsgBox "Entry not found, please reinstall Building Block.dotx " & _
      "or check with computer administrator", vbInformation, "Building Block " _
    & Chr(145) & strText & Chr(146)
End If
End Sub
Sub UseTheAboveDemo()
   Call InsertMyBuildingBlock("Front of Contract 2")
End Sub
'  Or..............
Sub UseItAnotherWay()
   Call InsertMyBuildingBlock("Front of Contract " & _
      InputBox("Enter ONLY number of contract front chunk. " & _
      "E.g.  1"))
End Sub
In the last example of Call, it is still the same input paramter:
InsertMyBuildingBlock(strBB_Name As String)
but what is passed as that parameter is constructed.
"Front of Contract "
plus the returned value of an Inputbox asking for the user to type in only a number.
They type 2, the result:  "Front of Contract 2" is passed as the input parameter to InsertMyBuildingBlock.
fumei
07-26-2010, 11:54 AM
Or.....if you have a bunch:
Front of Contract 1
Front of Contract 2
Front of Contract 3
Front of Contract 4
You could do all of them together (but sequentially of course) by:
Sub Yadda()
Dim ThoseChunks() As String
Dim j As Long
ThoseChunks = Split("1,2,3,4", ",")
For j = 0 To Ubound(ThoseChunks())
Call InsertMyBuildingBlock("Front of Contract " & ThoseChunks(j))
Next
End Sub
This would action things as:
InsertMyBuildingBlock("Front of Contract 1")
InsertMyBuildingBlock("Front of Contract 2")
InsertMyBuildingBlock("Front of Contract 3")
InsertMyBuildingBlock("Front of Contract 4")
fumei
07-26-2010, 12:00 PM
Or.....if you have a bunch:
Front of Contract 1
Front of Contract 2
Front of Contract 3
Front of Contract 4
You could do all of them together (but sequentially of course) by:
Sub Yadda()
Dim ThoseChunks() As String
Dim j As Long
ThoseChunks = Split("1,2,3,4", ",")
For j = 0 To Ubound(ThoseChunks())
Call InsertMyBuildingBlock("Front of Contract " & ThoseChunks(j))
Next
End Sub
This would action things as:
InsertMyBuildingBlock("Front of Contract 1")
InsertMyBuildingBlock("Front of Contract 2")
InsertMyBuildingBlock("Front of Contract 3")
InsertMyBuildingBlock("Front of Contract 4")
bstephens
07-26-2010, 02:22 PM
Thanks guys! I knew it must be something simple (wish I had more background in this stuff...) Your solution works beautifully, please note there was something weird about the message box in the code as posted above, I had to revise it as follows and now it works perfect!
Option Explicit
 
Sub InsertMyBuildingBlock(strBB_Name As String)
    Dim oTemplate As Template
    Dim oAddin As AddIn
    Dim bFound As Boolean
    Dim i As Long
     
     'Set the found flag default to False
    bFound = False
     
     'If the entry has still not been found
     'finally check the Building Blocks.dotx template
    If bFound = False Then
         
        Templates.LoadBuildingBlocks
        For Each oTemplate In Templates
            If oTemplate.Name = "Building Blocks.dotx" Then Exit For
        Next
        For i = 1 To Templates(oTemplate.FullName).BuildingBlockEntries.Count
            If Templates(oTemplate.FullName).BuildingBlockEntries(i).Name = strBB_Name Then
                Templates(oTemplate.FullName).BuildingBlockEntries(strBB_Name).Insert _
                Where:=Selection.Range
                 'set the found flag to true
                bFound = True
                 'Clean up and stop looking
                Set oTemplate = Nothing
                Exit Sub
            End If
        Next i
    End If
     
     'All sources have been checked and the entry is still not found
    If bFound = False Then 'so tell the user.
        MsgBox "Entry not found"
    End If
End Sub
 
Sub InsertMyBuildingBlock_BB1()
    Call InsertMyBuildingBlock("Counterparts (CEB)")
End Sub
fumei
07-26-2010, 02:52 PM
Ah, I missed changing one of your strText variables into strBB_Name.
 MsgBox "Entry not found, please reinstall Building Block.dotx " & _ 
"or check with computer administrator", vbInformation, "Building Block " _ 
& Chr(145) & strText & Chr(146) 
should be:[vba]
MsgBox "Entry not found, please reinstall Building Block.dotx " & _ 
"or check with computer administrator", vbInformation, "Building Block " _ 
& Chr(145) & strBB_Name & Chr(146) 
BTW:  just as a suggestion that will help you (and us)...
"please note there was something weird about the message box in the code as posted above,"
is not great.  Something weird is not descriptive.  You probably got a
Compile error;
variable not defined
Yes?  It will make it MUCH easier for you if, when mentioning errors, to state the error.  "Weird" is just weird.
This is not in any way meant to be critical, it really will make things easier in the long run if you always try to be be clear and concise.
bstephens
07-26-2010, 05:35 PM
Thanks, you're right, will do!
gmaxey
07-26-2010, 05:53 PM
Rather than checking every buildingblock name in a template against the passed parameter, it might be better to try to set a buildingblock object to the the desired name and use error handling:
 
Sub InsertMyBuildingBlock(strBB_Name As String)
Dim oTemplate As Template
Dim bFound As Boolean
Dim oBB As BuildingBlock
bFound = False
Templates.LoadBuildingBlocks
For Each oTemplate In Templates
  On Error Resume Next
  Set oBB = oTemplate.BuildingBlockEntries(strBB_Name)
  On Error GoTo 0
  If Not oBB Is Nothing Then
    bFound = True
    oTemplate.BuildingBlockEntries(strBB_Name).Insert Where:=Selection.Range
    Exit Sub
  End If
Next oTemplate
If Not bFound = True Then
  MsgBox "Entry not found, please reinstall Building Block.dotx " & _
  "or check with computer administrator", vbInformation, "Building Block " _
  & Chr(145) & strBB_Name & Chr(146)
End If
End Sub
gmaxey
07-26-2010, 07:18 PM
Actually this might be a bit more streamlined:
 
Sub InsertMyBuildingBlock(strBB_Name As String) 
    Dim oTemplate As Template 
    Dim oBB As BuildingBlock 
    Templates.LoadBuildingBlocks 
    For Each oTemplate In Templates 
        On Error Resume Next 
        Set oBB = oTemplate.BuildingBlockEntries(strBB_Name) 
        On Error Goto 0 
        If Not oBB Is Nothing Then 
            oTemplate.BuildingBlockEntries(strBB_Name).Insert Where:=Selection.Range 
        End If 
    Next oTemplate 
    MsgBox "Entry not found, please reinstall Building Block.dotx " & _ 
        "or check with computer administrator", vbInformation, "Building Block " _ 
        & Chr(145) & strBB_Name & Chr(146) 
End Sub
gmaxey
07-26-2010, 07:20 PM
Nope I left out the Exit Sub
 
Sub InsertMyBuildingBlock(strBB_Name As String) 
 Dim oTemplate As Template  
Dim oBB As BuildingBlock  
Templates.LoadBuildingBlocks 
 For Each oTemplate In Templates 
   On Error Resume Next 
   Set oBB = oTemplate.BuildingBlockEntries(strBB_Name) 
   On Error Goto 0 
   If Not oBB Is Nothing Then 
     oTemplate.BuildingBlockEntries(strBB_Name).Insert Where:=Selection.Range 
     Exit Sub 
   End If 
Next oTemplate 
MsgBox "Entry not found, please reinstall Building Block.dotx " & _ 
        "or check with computer administrator", vbInformation, "Building Block " _ 
        & Chr(145) & strBB_Name & Chr(146)  
End Sub
bstephens
07-26-2010, 11:46 PM
Thanks Greg, that works perfectly.  My code is looking far, far better now!
Best,
Brian
fumei
07-27-2010, 10:39 AM
Agreed.  Generally speaking it is always better to use objects rather than brute force processing.
Brian are you following why Greg's suggestion is better?
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.