I am quite new to vba and I need to write a script that has as input a document with some revisions. For each paragraph i would like to have in a table the original text (no revisions) and the final text (as if all revisions have been accepted). If this is to difficult I would like to at least have a table that contains the new text, the number of the paragraph in the original document and the number of the paragraph in the final version
Here an example of how could look like the input of the script
Here what i would like to have as output
Here what I have been able to do. I am not able to get the original text and in case of multiple phrases insertion the script is able to recognize only the first one as new line.
The script go through all the paragraph, if the paragraph contains no revision just the text is added in the table. If the text contains at list one revision all except the last revision are accepted and if the last the revision is an insert then if the paragraph text before and after all revisions have been accepted is the same the next paragraph is considered as new line. If the last revision is a delete then if the paragraph text before all revisions have been accepted is equal to the text of reviosion the text paragraph is considered as interely deleted.
Sub TrackchangesTable()
Dim oDoc As Document
Dim oNewDoc As Document
Dim oTable As Table
Dim oRow As Row
Dim oCol As Column
Dim oRange As Range
Dim oRevision As Revision
Dim strText As String
Dim Title As String
Dim Para As Paragraph
Dim NewLine As Boolean
Dim DraftText As String
Dim NewId As Long
Dim OldId As Long
Dim OldText As String
Dim Stile As String
Dim OriginalDoc As Document
Set oDoc = ActiveDocument
If oDoc.Revisions.Count = 0 Then
MsgBox "The active document contains no tracked changes.", vbOKOnly, Title
GoTo ExitHere
Else
If MsgBox("Do you want to extract tracked changes to a new document?" & vbCr & vbCr & , _
vbYesNo + vbQuestion) <> vbYes Then
GoTo ExitHere
End If
End If
Application.ScreenUpdating = False
Set oNewDoc = Documents.Add
oNewDoc.PageSetup.Orientation = wdOrientLandscape
With oNewDoc
.Content = ""
With .PageSetup
.LeftMargin = CentimetersToPoints(2)
.RightMargin = CentimetersToPoints(2)
.TopMargin = CentimetersToPoints(2.5)
End With
Set oTable = .Tables.Add _
(Range:=Selection.Range, _
numrows:=1, _
NumColumns:=7)
End With
With oNewDoc.Styles(wdStyleNormal)
With .Font
.Name = "Arial"
.Size = 9
.Bold = False
End With
With .ParagraphFormat
.LeftIndent = 0
End With
End With
With oTable
.Range.Style = wdStyleNormal
.AllowAutoFit = False
.PreferredWidthType = wdPreferredWidthPercent
.PreferredWidth = 100
For Each oCol In .Columns
oCol.PreferredWidthType = wdPreferredWidthPercent
Next oCol
.Columns(1).PreferredWidth = 5 'Page
.Columns(2).PreferredWidth = 5 'Note
.Columns(3).PreferredWidth = 10 'Final Text
.Columns(4).PreferredWidth = 15 'Inserted/deleted text
.Columns(5).PreferredWidth = 15 'Old Id
.Columns(6).PreferredWidth = 10 'New ID
.Columns(7).PreferredWidth = 10 'Stile
End With
With oTable.Rows(1)
.Cells(1).Range.Text = "Page"
.Cells(2).Range.Text = "Note"
.Cells(3).Range.Text = "Final Text"
.Cells(4).Range.Text = "Deleted Text"
.Cells(5).Range.Text = "Old Id"
.Cells(6).Range.Text = "New Id"
.Cells(7).Range.Text = "stile"
End With
NewLine = False
OldId = 1
NewId = 1
For Each Para In ThisDocument.Paragraphs
Stile = Para.Range.Style
If Para.Range.Revisions.Count = 0 And NewLine = False Then
StrTextFinale = Para.Range.Text
ElseIf Para.Range.Revisions.Count = 0 And NewLine = True Then
StrTextFinale = Para.Range.Text
Note = "New Line"
NewLine = False
OldId = OldId - 1
ElseIf Para.Range.Revisions.Count > 0 Then
For i = 1 To Para.Range.Revisions.Count
If i < Para.Range.Revisions.Count Then
Para.Range.Revisions(i).Accept
Else
If Para.Range.Revisions(i).Type = wdRevisionInsert Then
DraftText = Para.Range.Text
Para.Range.Revisions(i).Accept
StrTextFinale = Para.Range.Text
If DraftText = StrTextFinale Then
NewLine = True
End If
ElseIf Para.Range.Revisions(i).Type = wdRevisionDelete Then
DraftText = Para.Range.Revisions(i).Range.Text
StrTextFinale = Para.Range.Text
If DraftText = StrTextFinale Then
Note = "Testo eliminato"
StrTextFinale = "volutamente cancellato"
OldText = Para.Range.Text
NewId = NewId - 1
Else
Para.Range.Revisions(i).Accept
StrTextFinale = Para.Range.Text
End If
End If
End If
Next
End If
Set oRow = oTable.Rows.Add
With oRow
.Cells(1).Range.Text = Para.Range.Information(wdActiveEndAdjustedPageNumber)
.Cells(2).Range.Text = Note
.Cells(3).Range.Text = StrTextFinale
.Cells(4).Range.Text = OldText
.Cells(5).Range.Text = OldId
.Cells(6).Range.Text = NewId
.Cells(7).Range.Text = Stile
Note = ""
End With
OldId = OldId + 1
NewId = NewId + 1
OldText = ""
Next
With oTable.Rows(1)
.Range.Font.Bold = True
.HeadingFormat = True
End With
Application.ScreenUpdating = True
Application.ScreenRefresh
MsgBox ("Over")
ExitHere:
Set oDoc = Nothing
Set oNewDoc = Nothing
Set oTable = Nothing
Set oRow = Nothing
Set oRange = Nothing
End Sub
Can somebody help me to improve this script?
Related
I am trying to split pdf, based on the pages where it finds ".pdf" however when I try to save the pdf with a dynamic string variable, it do not save the pdf but when I write hardcode file path it output the pdf. do not know what is going on here.
the following code is not finished yet I am stuck in creating new pdf with deleted pages:
Function Extract_PDF()
Dim aApp As Acrobat.CAcroApp
Dim av_Doc As Acrobat.CAcroAVDoc
Dim pdf_Doc As Acrobat.CAcroPDDoc '
Dim newPDFdoc As Acrobat.CAcroPDDoc
Dim Sel_Text As Acrobat.CAcroPDTextSelect
Dim i As Long, j As Long
Dim pageNum, Content
Dim pageContent As Acrobat.CAcroHiliteList
Dim found As Boolean
Dim foundPage As Integer
Dim PDF_Path As String
Dim pdfName As String
Dim folerPath As String
Dim FileExplorer As FileDialog
Set FileExplorer = Application.FileDialog(msoFileDialogFilePicker)
With FileExplorer
.AllowMultiSelect = False
.InitialFileName = ActiveDocument.Path
.Filters.Clear
.Filters.Add "PDF File", "*.pdf"
If .Show = -1 Then
PDF_Path = .SelectedItems.Item(1)
Else
PagesLB = "Catch me Next Time ;)"
PDF_Path = ""
Exit Function
End If
End With
Set aApp = CreateObject("AcroExch.App")
Set av_Doc = CreateObject("AcroExch.AVDoc")
If av_Doc.Open(PDF_Path, vbNull) <> True Then Exit Function
While av_Doc Is Nothing
Set av_Doc = aApp.GetActiveDoc
Wend
av_Doc.BringToFront
aApp.Show
Set pdf_Doc = av_Doc.GetPDDoc
For i = pdf_Doc.GetNumPages - 1 To 0 Step -1
Set pageNum = pdf_Doc.AcquirePage(i)
Set pageContent = CreateObject("AcroExch.HiliteList")
If pageContent.Add(0, 9000) <> True Then Exit Function
Set Sel_Text = pageNum.CreatePageHilite(pageContent)
Content = ""
found = False
For j = 0 To Sel_Text.GetNumText - 1
Content = Content & Sel_Text.GetText(j)
If InStr(1, Content, ".pdf") > 0 Then
found = True
foundPage = i
pdfName = Content
Exit For
End If
Next j
If found Then
PDF_Path = Left(PDF_Path, InStrRev(PDF_Path, "\")) & ValidWBName(pdfName)
Set newPDFdoc = CreateObject("AcroExch.PDDoc")
Set newPDFdoc = av_Doc.GetPDDoc
If newPDFdoc.DeletePages(0, i - 1) = False Then
Debug.Print "Failed"
Else
Debug.Print "done"
End If
If newPDFdoc.Save(PDSaveFull, PDF_Path) = False Then
Debug.Print "Failed to save pdf "
Else
Debug.Print "Saved"
End If
newPDFdoc.Close
End If
Next i
av_Doc.Close False
aApp.Exit
Set av_Doc = Nothing
Set pdf_Doc = Nothing
Set aApp = Nothing
End Function
ValidWBName:
Function ValidWBName(agr As String) As String
Dim RegEx As Object
Set RegEx = CreateObject("VBScript.RegExp")
With RegEx
.Pattern = "[\\/:\*\?""<>\|]"
.Global = True
ValidWBName = .Replace(agr, "")
End With
End Function
in above function when it finds the word pdf it try to create a new instance of pdf and remove previous pages.
If found Then
PDF_Path = Left(PDF_Path, InStrRev(PDF_Path, "\")) & ValidWBName(pdfName)
Set newPDFdoc = CreateObject("AcroExch.PDDoc")
Set newPDFdoc = av_Doc.GetPDDoc
If newPDFdoc.DeletePages(0, i - 1) = False Then
Debug.Print "Failed"
Else
Debug.Print "done"
End If
If newPDFdoc.Save(PDSaveFull, PDF_Path) = False Then
Debug.Print "Failed to save pdf "
Else
Debug.Print "Saved"
End If
newPDFdoc.Close
End If
this line "Failed to save pdf"
If newPDFdoc.Save(PDSaveFull, PDF_Path) = False Then
but when I write hardcode path it create the pdf
If newPDFdoc.Save(PDSaveFull, "C:\Users\MBA\Desktop\PDF Project 2\Murdoch_Michael__Hilary_PIA_19.pdf") = False Then
the culprit HAD to be in ValidWBName() function, which didn't handle all possible not allowed chars for a valid file name
since it came out vbCr char was one of them, you could change it as follows:
Function ValidWBName(agr As String) As String
Dim RegEx As Object
Set RegEx = CreateObject("VBScript.RegExp")
With RegEx
.Pattern = "[\\/:\*\?""<>\|" & Chr(13) & "]" ' <-- added vbCr
.Global = True
ValidWBName = .Replace(agr, "")
End With
End Function
Scenario
I have a word document where I have a table as shown in Image 1. The checkboxes are used to show the next contents. For example, I have in first step yes and no, when yes is checked the next content is shown. And in next step, I have thre Checkboxes with case 1,2 and 3 respectively.
When the case 1 is checked I have next a text that is filled via vba as F1Feld1...till F4Feld1.
Problem
First problem is, I am unable to create a function where only yes and no can be checked as well as either of the case can be checked. Second, problem is that the vba for case checkboxes run perfectly when I have them created separate but when combined together only case 1 vba runs.
Following is my code:
Option Explicit
Dim tabelle As Table, zelle As Cell
Private Sub Document_ContentControlOnEnter(ByVal CC As ContentControl)
Dim r As Range
Set tabelle = ActiveDocument.Bookmarks("local").Range.Tables(1)
If ActiveDocument.SelectContentControlsByTag("Yes").Item(1).Checked = True Then
ActiveDocument.SelectContentControlsByTag("No").Item(1).Checked = False
Call local_blockiert
Else: Call local_offen
End If
If ActiveDocument.SelectContentControlsByTag("Case1").Item(1).Checked = True Then
On Error Resume Next
With ActiveDocument
.Bookmarks("TB1").Range.Text = "F1Feld1": .Bookmarks("TB1").Range.Font.ColorIndex = wdBlack
.Bookmarks("TB2").Range.Text = "F1Fed2": .Bookmarks("TB2").Range.Font.ColorIndex = wdBlack
.Bookmarks("TB3").Range.Text = "F1Feld3": .Bookmarks("TB3").Range.Font.ColorIndex = wdBlack
.Bookmarks("TB4").Range.Text = "F1Feld4": .Bookmarks("TB4").Range.Font.ColorIndex = wdBlack
End With
ElseIf ActiveDocument.SelectContentControlsByTag("Case1").Item(1).Checked = False Then
With ActiveDocument
.Bookmarks("TB1").Range.Text = ""
.Bookmarks("TB2").Range.Text = ""
.Bookmarks("TB3").Range.Text = ""
.Bookmarks("TB4").Range.Text = ""
End With
ElseIf ActiveDocument.SelectContentControlsByTag("Case2").Item(1).Checked = True Then
With ActiveDocument
.Bookmarks("TB1").Range.Text = "F2Feld1": .Bookmarks("TB1").Range.Font.ColorIndex = wdBlack
.Bookmarks("TB2").Range.Text = "F2Fed2": .Bookmarks("TB2").Range.Font.ColorIndex = wdBlack
.Bookmarks("TB3").Range.Text = "F2Feld3": .Bookmarks("TB3").Range.Font.ColorIndex = wdBlack
.Bookmarks("TB4").Range.Text = "F2Feld4": .Bookmarks("TB4").Range.Font.ColorIndex = wdBlack
End With
ElseIf ActiveDocument.SelectContentControlsByTag("Case2").Item(1).Checked = False Then
With ActiveDocument
.Bookmarks("TB1").Range.Text = ""
.Bookmarks("TB2").Range.Text = ""
.Bookmarks("TB3").Range.Text = ""
.Bookmarks("TB4").Range.Text = ""
End With
ElseIf ActiveDocument.SelectContentControlsByTag("Case3").Item(1).Checked = True Then
With ActiveDocument
.Bookmarks("TB1").Range.Text = "F3Feld1": .Bookmarks("TB1").Range.Font.ColorIndex = wdBlack
.Bookmarks("TB2").Range.Text = "F3Fed2": .Bookmarks("TB2").Range.Font.ColorIndex = wdBlack
.Bookmarks("TB3").Range.Text = "F3Feld3": .Bookmarks("TB3").Range.Font.ColorIndex = wdBlack
.Bookmarks("TB4").Range.Text = "F3Feld4": .Bookmarks("TB4").Range.Font.ColorIndex = wdBlack
End With
ElseIf ActiveDocument.SelectContentControlsByTag("Case3").Item(1).Checked = False Then
With ActiveDocument
.Bookmarks("TB1").Range.Text = ""
.Bookmarks("TB2").Range.Text = ""
.Bookmarks("TB3").Range.Text = ""
.Bookmarks("TB4").Range.Text = ""
End With
End If
End Sub
Private Sub local_blockiert()
Dim i As Long, j As Long
On Error GoTo fehler
With ActiveDocument.Bookmarks("local").Range
.Font.ColorIndex = wdWhite
End With
fehler:
Call AllesAuf
End Sub
Private Sub local_offen()
Dim i As Long, j As Long
On Error GoTo fehler
With ActiveDocument.Bookmarks("YesorNo").Range
.Font.ColorIndex = wdBlack
End With
fehler:
Call AllesAuf
End Sub
Private Sub yes_blockiert()
Dim j As Long
On Error GoTo fehler
With tabelle.Cell(2, 2)
.Shading.ForegroundPatternColorIndex = wdGray25
.Range.Font.ColorIndex = wdGray25
For j = 1 To .Range.ContentControls.Count
.Range.ContentControls(j).LockContents = True
Next j
End With
Exit Sub
fehler:
Call AllesAuf
End Sub
Private Sub yes_offen()
Dim j As Long
On Error GoTo fehler
With tabelle.Cell(2, 2)
For j = 1 To .Range.ContentControls.Count
.Range.ContentControls(j).LockContents = False
Next j
.Shading.ForegroundPatternColor = RGB(255, 242, 204)
.Range.Font.ColorIndex = wdAuto
End With
Exit Sub
fehler:
Call AllesAuf
End Sub
Private Sub AllesAuf()
Dim i As Long
With ActiveDocument
For i = 1 To .ContentControls.Count
.ContentControls(i).LockContents = False
Next i
End With
End Sub
I am trying to write a Macro that can display the final proposed text in a tracked change without having to accept the change.
Current code (modified from thedoctools.com) is as follows which uses a Revision object only for Delete and Insert types:
Public Sub ExtractAllRevisionsToExcel()
Dim oDoc As Document
Dim xlApp As Excel.Application
Dim xlWB As Excel.Workbook
Dim oNewExcel As Worksheet
Dim oRange As Range
Dim oRevision As Revision
Dim strText As String
Dim index As Long
Dim Title As String
Title = "Extract All revisions to Excel"
Set oDoc = ActiveDocument
If ActiveDocument.Revisions.Count = 0 Then
MsgBox "The active document contains no changes.", vbOKOnly, Title
GoTo ExitHere
End If
Application.ScreenUpdating = True
'Create a new excel for the revisions
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True
Set xlWB = xlApp.Workbooks.Add 'create a new workbook
Set oNewExcel = xlWB.Worksheets(1)
With oNewExcel
.Cells(1, 1).Formula = "Document"
.Cells(1, 2).Formula = "Page"
.Cells(1, 3).Formula = "line number"
.Cells(1, 4).Formula = "Original Statement"
.Cells(1, 5).Formula = "Statement Proposed"
index = 1
'Get info from each tracked change (insertion/deletion) from oDoc and insert in table
For Each oRevision In oDoc.Revisions
Select Case oRevision.Type
'Only include insertions and deletions
Case wdRevisionInsert, wdRevisionDelete
'In case of footnote/endnote references (appear as Chr(2)),
'insert "[footnote reference]"/"[endnote reference]"
With oRevision
'Get the changed text
strText = .Range.Text
Set oRange = .Range
Do While InStr(1, oRange.Text, Chr(2)) > 0
'Find each Chr(2) in strText and replace by appropriate text
i = InStr(1, strText, Chr(2))
If oRange.Footnotes.Count = 1 Then
strText = Replace(Expression:=strText, _
Find:=Chr(2), Replace:="[footnote reference]", _
Start:=1, Count:=1)
'To keep track of replace, adjust oRange to start after i
oRange.Start = oRange.Start + i
ElseIf oRange.Endnotes.Count = 1 Then
strText = Replace(Expression:=strText, _
Find:=Chr(2), Replace:="[endnote reference]", _
Start:=1, Count:=1)
'To keep track of replace, adjust oRange to start after i
oRange.Start = oRange.Start + i
End If
Loop
End With
index = index + 1 'Add 1 to row
'Insert data in cells in row
'The document name
.Cells(index, 1).Formula = oDoc.FullName & vbCr
'Page number
.Cells(index, 2).Formula = oRevision.Range.Information(wdActiveEndPageNumber)
'Line number - start of revision
.Cells(index, 3).Formula = oRevision.Range.Information(wdFirstCharacterLineNumber)
'Original section text
.Cells(index, 4).Formula = oRevision.Range.Paragraphs(1).Range.Text
'Proposed changes - THIS IS WHERE I WANT TO SEE THE PREVIEW OF THE FINAL SECTION AFTER CHANGE IS ACCEPTED
If oRevision.Type = wdRevisionInsert Then
.Cells(index, 5).Formula = strText
'Apply automatic color (black on white)
.Cells(index, 5).Font.Color = wdColorBlue
Else
.Cells(index, 5).Formula = strText
'Apply red color
.Cells(index, 5).Font.Color = wdColorRed
End If
End Select
Next oRevision
End With
'Repaginate
ActiveDocument.Repaginate
'Toggle nonprinting characters twice
ActiveWindow.ActivePane.View.ShowAll = Not _
ActiveWindow.ActivePane.View.ShowAll
ActiveWindow.ActivePane.View.ShowAll = Not _
ActiveWindow.ActivePane.View.ShowAll
Application.ScreenUpdating = True
Application.ScreenRefresh
oNewExcel.Activate
MsgBox ActiveDocument.Revisions.Count & " changes found. Finished creating the worksheet.", vbOKOnly, Title
ExitHere:
Set oDoc = Nothing
Set xlWB = Nothing
Set xlApp = Nothing
Set oNewExcel = Nothing
Set oRange = Nothing
End Sub
The variable strText returns only the portion we are changing in oRevision.Range.Paragraphs(1).Range.Text, however I want a variable that returns the final text in oRevision.Range.Paragraphs(1).Range.Text AFTER the change has already been accepted, but without accepting the change in the actual Word document.
Is there a way to get such a variable as I just want to have a preview of the final section after the change is accepted, without accepting the change.
Even Word's macro recorder can give you the code for that:
With ActiveWindow.View
.ShowRevisionsAndComments = False
.RevisionsView = wdRevisionsViewFinal
End With
I am trying to use VBA to create a Word document with multiple tables each on a new page (using a loop) compiled with cell information from Excel.
So far everything works fantastically except after inserting the first table it is replaced by the second table, then the third table replaces the second, and so on. What I am left with is only the last created table.
I'm not sure how to cause a new table to be created instead of replacing the previously created table.
Screen shot of Excel table
Sub Export_to_Word()
'(1) Word objects.
Dim wdApp As Word.Application
Dim wdDoc As Word.Document
Dim wdCell As Word.Cell
Dim wdTabl As Word.Table
Dim wdRange As Word.Range
'(2) Excel objects
Dim wbBook As Workbook
Dim wsSheet As Worksheet
Dim strValue As String
Dim i As Integer
Dim x As Integer
'For assiging integer value to calculate number of table rows
Dim ARows As Integer
Dim BRows As Integer
Dim CRows As Integer
Dim DRows As Integer
'For copying question part as a value in the excel sheet
Dim QueNum As Variant
Dim PartA As Variant
Dim PartB As Variant
Dim PartC As Variant
Dim PartD As Variant
'For copying the question in the excel sheet
Dim QueA As Variant
Dim QueB As Variant
Dim QueC As Variant
Dim QueD As Variant
'For copying question part as a value in the excel sheet
Dim MarkA As Variant
Dim MarkB As Variant
Dim MarkC As Variant
Dim MarkD As Variant
'For copying the answers in the excel sheet
Dim AnsA As Variant
Dim AnsB As Variant
Dim AnsC As Variant
Dim AnsD As Variant
'For copying the header values in the excel sheet
Dim CandCode As Variant
Dim AnPath As Variant
Dim Logo As Variant
Dim EngNam As Variant
Dim EngTex As Variant
Dim FreNam As Variant
Dim FreTex As Variant
'(4) Initialize the Excel objects
Set wbBook = ThisWorkbook
Set wsSheet = wbBook.Worksheets("Sheet1")
'(5)Create table in excel before copying to word
'Create Word file.
Set wdApp = New Word.Application
wdApp.Visible = True
Set wdDoc = wdApp.Documents.Add
'(5a)Enter excel values into header
With wdDoc.Sections(1)
.Headers(wdHeaderFooterPrimary).Range.Text = CandCode & vbCr & vbCr & AnPath
.Headers(wdHeaderFooterPrimary).Range.Font.Name = "Arial"
.Headers(wdHeaderFooterPrimary).Range.Font.Size = 7
.Headers(wdHeaderFooterPrimary).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
End With
'(5b)Start of new cycle for loop
For i = 4 To 6
'(5c) Equate cell values to the the variables defined under Excel objects (Part 2). N.B in equation "Cells(3,i) 3= row number and i=column number
ARows = wsSheet.Cells(3, i).Value
BRows = wsSheet.Cells(7, i).Value
CRows = wsSheet.Cells(11, i).Value
DRows = wsSheet.Cells(15, i).Value
QueNum = wsSheet.Cells(1, i).Value
PartA = wsSheet.Range("A2").Value
PartB = wsSheet.Range("A6").Value
PartC = wsSheet.Range("A10").Value
PartD = wsSheet.Range("A14").Value
QueA = wsSheet.Cells(2, i).Value
QueB = wsSheet.Cells(6, i).Value
QueC = wsSheet.Cells(10, i).Value
QueD = wsSheet.Cells(14, i).Value
MarkA = wsSheet.Cells(4, i).Value
MarkB = wsSheet.Cells(8, i).Value
MarkC = wsSheet.Cells(12, i).Value
MarkD = wsSheet.Cells(16, i).Value
AnsA = wsSheet.Cells(5, i).Value
AnsB = wsSheet.Cells(9, i).Value
AnsC = wsSheet.Cells(13, i).Value
AnsD = wsSheet.Cells(17, i).Value
CandCode = wsSheet.Range("V24").Value
AnPath = wsSheet.Range("V25").Value
Logo = wsSheet.Range("V26").Value
EngNam = wsSheet.Range("V27").Value
EngTex = wsSheet.Range("V28").Value
FreNam = wsSheet.Range("V29").Value
FreTex = wsSheet.Range("V30").Value
'(5d)Creates variables that identifes location of each of the rows with the question part
TotRows = ARows + BRows + CRows + DRows + 5
QuesA_row = 2
QuesB_row = ARows + 3
QuesC_row = ARows + BRows + 4
QuesD_row = ARows + BRows + CRows + 5
'(5e)Create Word table
Set wdRange = wdDoc.Range
wdDoc.Tables.Add wdRange, NumRows:=(TotRows), NumColumns:=5, DefaultTableBehavior:=wdWord8TableBehavior, AutoFitBehavior:=wdAutoFitWindow
Set wdTabl = wdDoc.Tables(1)
'(5f)Edit Table
With wdTabl
.ApplyStyleHeadingRows = False
.ApplyStyleLastRow = False
.ApplyStyleFirstColumn = False
.ApplyStyleLastColumn = True
.ApplyStyleRowBands = False
.ApplyStyleColumnBands = False
'Changes font of table
.Range.Font.Name = "Arial"
.Range.Font.Size = "10"
'Changes spacing of lines in table to single
.Range.ParagraphFormat.SpaceBeforeAuto = False
.Range.ParagraphFormat.SpaceBefore = 8
.Range.ParagraphFormat.SpaceAfterAuto = False
.Range.ParagraphFormat.SpaceAfter = 0
.Range.ParagraphFormat.LineSpacingRule = wdLineSpaceSingle
.Range.ParagraphFormat.PageBreakBefore = False
'Adjust column widths
.Columns(1).SetWidth ColumnWidth:=20, RulerStyle:=wdAdjustNone
.Columns(2).SetWidth ColumnWidth:=23, RulerStyle:=wdAdjustNone
.Columns(3).SetWidth ColumnWidth:=400, RulerStyle:=wdAdjustNone
.Columns(4).SetWidth ColumnWidth:=11, RulerStyle:=wdAdjustNone
.Columns(5).SetWidth ColumnWidth:=40, RulerStyle:=wdAdjustNone
'Shading for marks column & borders
.Borders.Enable = False
.Columns(5).Shading.BackgroundPatternColor = wdColorGray20
.Columns(5).Borders(wdBorderTop).Color = wdColorBlack
.Columns(5).Borders(wdBorderTop).LineStyle = Options.DefaultBorderLineStyle
.Columns(5).Borders(wdBorderTop).LineWidth = Options.DefaultBorderLineWidth
.Columns(5).Borders(wdBorderLeft).Color = wdColorBlack
.Columns(5).Borders(wdBorderLeft).LineStyle = Options.DefaultBorderLineStyle
.Columns(5).Borders(wdBorderLeft).LineWidth = Options.DefaultBorderLineWidth
.Columns(5).Borders(wdBorderRight).Color = wdColorBlack
.Columns(5).Borders(wdBorderRight).LineStyle = Options.DefaultBorderLineStyle
.Columns(5).Borders(wdBorderRight).LineWidth = Options.DefaultBorderLineWidth
.Columns(5).Borders(wdBorderBottom).Color = wdColorBlack
.Columns(5).Borders(wdBorderBottom).LineStyle = Options.DefaultBorderLineStyle
.Columns(5).Borders(wdBorderBottom).LineWidth = Options.DefaultBorderLineWidth
.Columns(5).Cells(1).Borders(wdBorderBottom).Color = wdColorBlack
.Columns(5).Cells(1).Borders(wdBorderBottom).LineStyle = Options.DefaultBorderLineStyle
.Columns(5).Cells(1).Borders(wdBorderBottom).LineWidth = Options.DefaultBorderLineWidth
'Underlines for questions
.Columns(3).Cells.Borders.InsideLineStyle = wdLineStyleSingle 'Adds bottom border to all cells in column 3
.Columns(3).Cells(1).Borders(wdBorderBottom).Color = wdColorWhite 'Removes bottom border
.Columns(3).Cells(1).Borders(wdBorderBottom).LineStyle = Options.DefaultBorderLineStyle
.Columns(3).Cells(1).Borders(wdBorderBottom).LineWidth = Options.DefaultBorderLineWidth
.Columns(3).Cells(QuesA_row).Borders(wdBorderBottom).Color = wdColorWhite 'Removes bottom border
.Columns(3).Cells(QuesA_row).Borders(wdBorderBottom).LineStyle = Options.DefaultBorderLineStyle
.Columns(3).Cells(QuesA_row).Borders(wdBorderBottom).LineWidth = Options.DefaultBorderLineWidth
.Columns(3).Cells(QuesB_row).Borders(wdBorderBottom).Color = wdColorWhite 'Removes bottom border
.Columns(3).Cells(QuesB_row).Borders(wdBorderBottom).LineStyle = Options.DefaultBorderLineStyle
.Columns(3).Cells(QuesB_row).Borders(wdBorderBottom).LineWidth = Options.DefaultBorderLineWidth
.Columns(3).Cells(QuesC_row).Borders(wdBorderBottom).Color = wdColorWhite 'Removes bottom border
.Columns(3).Cells(QuesC_row).Borders(wdBorderBottom).LineStyle = Options.DefaultBorderLineStyle
.Columns(3).Cells(QuesC_row).Borders(wdBorderBottom).LineWidth = Options.DefaultBorderLineWidth
.Columns(3).Cells(QuesD_row).Borders(wdBorderBottom).Color = wdColorWhite 'Removes bottom border
.Columns(3).Cells(QuesD_row).Borders(wdBorderBottom).LineStyle = Options.DefaultBorderLineStyle
.Columns(3).Cells(QuesD_row).Borders(wdBorderBottom).LineWidth = Options.DefaultBorderLineWidth
.Columns(3).Cells(TotRows).Borders(wdBorderBottom).Color = wdColorBlack 'Adds border to bottom row of column
.Columns(3).Cells(TotRows).Borders(wdBorderBottom).LineStyle = Options.DefaultBorderLineStyle
.Columns(3).Cells(TotRows).Borders(wdBorderBottom).LineWidth = Options.DefaultBorderLineWidth
'Enter Data into table
.Columns(1).Cells(2).Range.Text = QueNum & "."
.Columns(2).Cells(QuesA_row).Range.Text = PartA
.Columns(2).Cells(QuesB_row).Range.Text = PartB
.Columns(2).Cells(QuesC_row).Range.Text = PartC
.Columns(2).Cells(QuesD_row).Range.Text = PartD
.Columns(3).Cells(QuesA_row).Range.Text = QueA
.Columns(3).Cells(QuesB_row).Range.Text = QueB
.Columns(3).Cells(QuesC_row).Range.Text = QueC
.Columns(3).Cells(QuesD_row).Range.Text = QueD
.Columns(5).Cells(1).Range.Text = "Marks"
.Columns(5).Cells(QuesA_row).Range.Text = MarkA
.Columns(5).Cells(QuesB_row).Range.Text = MarkB
.Columns(5).Cells(QuesC_row).Range.Text = MarkC
.Columns(5).Cells(QuesD_row).Range.Text = MarkD
'Modifying marks column
.Columns(5).Cells(1).Range.Font.Bold = True 'Modifys "marks" cell
.Columns(5).Cells(1).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Columns(5).Cells(1).Range.Cells.VerticalAlignment = wdCellAlignVerticalBottom
.Columns(5).Cells(QuesA_row).Range.Font.Bold = True
.Columns(5).Cells(QuesA_row).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Columns(5).Cells(QuesA_row).Range.Cells.VerticalAlignment = wdCellAlignVerticalTop
.Columns(5).Cells(QuesB_row).Range.Font.Bold = True
.Columns(5).Cells(QuesB_row).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Columns(5).Cells(QuesB_row).Range.Cells.VerticalAlignment = wdCellAlignVerticalTop
.Columns(5).Borders(wdBorderTop).Color = wdColorBlack
.Columns(5).Cells(QuesB_row).Borders(wdBorderTop).LineStyle = Options.DefaultBorderLineStyle
.Columns(5).Cells(QuesB_row).Borders(wdBorderTop).LineWidth = Options.DefaultBorderLineWidth
.Columns(5).Cells(QuesC_row).Range.Font.Bold = True
.Columns(5).Cells(QuesC_row).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Columns(5).Cells(QuesC_row).Range.Cells.VerticalAlignment = wdCellAlignVerticalTop
.Columns(5).Borders(wdBorderTop).Color = wdColorBlack
.Columns(5).Cells(QuesC_row).Borders(wdBorderTop).LineStyle = Options.DefaultBorderLineStyle
.Columns(5).Cells(QuesC_row).Borders(wdBorderTop).LineWidth = Options.DefaultBorderLineWidth
.Columns(5).Cells(QuesD_row).Range.Font.Bold = True
.Columns(5).Cells(QuesD_row).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Columns(5).Cells(QuesD_row).Range.Cells.VerticalAlignment = wdCellAlignVerticalTop
.Columns(5).Borders(wdBorderTop).Color = wdColorBlack
.Columns(5).Cells(QuesD_row).Borders(wdBorderTop).LineStyle = Options.DefaultBorderLineStyle
.Columns(5).Cells(QuesD_row).Borders(wdBorderTop).LineWidth = Options.DefaultBorderLineWidth
'Adjusts text alignment in question column
.Columns(3).Cells.VerticalAlignment = wdCellAlignVerticalBottom
' Exit table and insert page break so next table starts at beginning of page
With wdRange
.Collapse Direction:=wdCollapseEnd
.InsertParagraphAfter
.InsertBreak Type:=wdPageBreak
.Collapse Direction:=wdCollapseEnd
End With
End With
Next i
'(7)Identifies all numbered words and replaces them with all caps bold
Dim A(10) As String
A(1) = "one"
A(2) = "two"
A(3) = "three"
A(4) = "four"
A(5) = "five"
A(6) = "six"
A(7) = "seven"
A(8) = "eight"
A(9) = "nine"
A(10) = "ten"
Set wdRange = ActiveDocument.Content
With wdRange
For x = 1 To 10
.Find.ClearFormatting
.Find.Replacement.ClearFormatting
.Find.Replacement.Font.Bold = True
With .Find
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Replacement.Font.Bold = True
.Replacement.Font.Allcaps = True
wdRange.Find.Execute FindText:=A(x), ReplaceWith:=A(x), Format:=True, _
Replace:=wdReplaceAll
End With
Next x
End With
'(8)Null out the variables.
Set wdCell = Nothing
Set wdDoc = Nothing
Set wdApp = Nothing
Set wdRange = Nothing
Set wdTabl = Nothing
'(9) Adds message box to show complete
MsgBox "Success! The exam questions are complete!", vbInformation
End Sub
This stripped-down version worked for me:
Sub Export_to_Word()
Dim wdApp As Word.Application, i As Long, wdDoc As Word.Document
Dim wdCell As Word.Cell, wdTabl As Word.Table, wdRange As Word.Range
Dim wbBook As Workbook, wsSheet As Worksheet
Set wbBook = ThisWorkbook
Set wsSheet = wbBook.Worksheets("Sheet1")
Set wdApp = New Word.Application
wdApp.Visible = True
Set wdDoc = wdApp.Documents.Add
For i = 1 To 5
wdDoc.Paragraphs.Add
Set wdRange = ActiveDocument.Paragraphs.Last.Range
Set wdTabl = wdDoc.Tables.Add(wdRange, NumRows:=5, NumColumns:=5, _
DefaultTableBehavior:=wdWord8TableBehavior, _
AutoFitBehavior:=wdAutoFitWindow)
With wdTabl
.Borders.Enable = True
.Columns(1).Cells(1).Range.Text = "First"
.Columns(5).Cells(5).Range.Text = "Last"
End With
Next i
End Sub
You set up only one table.
'(5e)Create Word table
Set wdRange = wdDoc.Range
wdDoc.Tables.Add wdRange, NumRows:=(TotRows), NumColumns:=5, DefaultTableBehavior:=wdWord8TableBehavior, AutoFitBehavior:=wdAutoFitWindow
Set wdTabl = wdDoc.Tables(1)
Change code.
'(5e)Create Word table
Set wdRange = wdDoc.Range
Set wdTabl = wdDoc.Tables.Add(wdRange, NumRows:=(TotRows), NumColumns:=5, DefaultTableBehavior:=wdWord8TableBehavior, AutoFitBehavior:=wdAutoFitWindow)
'Set wdTabl = wdDoc.Tables(1)
I have a VBA macro for Microsoft Word that I am trying to improve.
The purpose of the macro is to bold and italicize all words in a document that match the search terms in the first table of the document.
The problem is the search terms include wildcards which are the following:
the hyphen "-": between letters a wildcard for either a space or a period
asterisk "&": (the site is not letting me put in asterisks as this is the markdown for italicize, so I'll put in the & symbol instead to get around the filters) a wildcard for any number of characters at the beginning of a word or at the end. Unlike normal programming languages though, when it is used in the middle of the word it needs to be combined with the hyphen to be a wildcard for a range of characters. For example "th&-e" would pick up "there" while "th&e" would not.
question mark "?": wildcard for a single character
What I am doing so far is just testing for these characters and if they are present I either lop them off in the case of the asterisk, or I alert the user that they have to search for the word manually. Not ideal :-P
I have tried the .MatchWildcard property in VBA but have not yet gotten it to work. I have a feeling it has something to do with the replacement text, not the search text.
A working macro will take the following as its input (the first row is intentionally ignored and the second column is the one with the target search terms):
Imagine this in a table all in the second column (as the html allowed here doesn't allow tr and td etc)
First row: Word
Second row: Search
Third row: &earch1
Fourth row: Search2&
Fifth row: S-earch3
Sixth row: S?arch4
Seventh row: S&-ch5
And it will search the document and replace with bold and italicized content like so:
Search Search1 Search2 Search3 Search4 Search5
Note: S-earch3 could also pick up S.earch3 and replace with Search3
As one might assume the search terms will usually not be right next to each other - the macro should find all instances.
I will include my attempted but nonfunctional code as well after the first working macro.
The code for the working macro will be on pastebin for a month from today, which is 9/17/09, at the following url.
Thanks again for any thoughts and help you might have to offer!
Sara
Working VBA Macro:
Sub AllBold()
Dim tblOne As Table
Dim celTable As Cell
Dim rngTable As Range
Dim intCount As Integer
Dim celColl As Cells
Dim i As Integer
Dim rngLen As Integer
Dim bolWild As Boolean
Dim strWild As String
Set tblOne = ActiveDocument.Tables(1)
intCount = tblOne.Columns(2).Cells.Count
Set celColl = tblOne.Columns(2).Cells
strWild = ""
For i = 1 To intCount
If i = 1 Then
i = i + 1
End If
Set celTable = ActiveDocument.Tables(1).Cell(Row:=i, Column:=2)
Set rngTable = ActiveDocument.Range(Start:=celTable.Range.Start, _
End:=celTable.Range.End - 1)
rngLen = Len(rngTable.Text)
bolWild = False
If (Mid(rngTable.Text, rngLen, 1) = "&") Then 'remember to replace & with asterisk!'
rngTable.SetRange Start:=rngTable.Start, End:=rngTable.End - 1
End If
If (Mid(rngTable.Text, 1, 1) = "&") Then 'remember to replace & with asterisk!'
rngTable.SetRange Start:=rngTable.Start + 1, End:=rngTable.End
End If
If InStr(1, rngTable.Text, "-", vbTextCompare) > 0 Then
strWild = strWild + rngTable.Text + Chr$(13)
bolWild = True
End If
If InStr(1, rngTable.Text, "?", vbTextCompare) > 0 Then
strWild = strWild + rngTable.Text + Chr$(13)
bolWild = True
End If
If (bolWild = False) Then
Dim oRng As Word.Range
Set oRng = ActiveDocument.Range
With oRng.Find
.ClearFormatting
.Text = rngTable.Text
With .Replacement
.Text = rngTable.Text
.Font.Bold = True
.Font.Italic = True
End With
.Execute Replace:=wdReplaceAll
End With
End If
Next
If bolWild = True Then
MsgBox ("Please search the following strings with - or ? manually:" + Chr$(13) + strWild)
End If
End Sub
Attempted Nonfunctional VBA Macro:
Sub AllBoldWildcard()
Dim tblOne As Table
Dim celTable As Cell
Dim rngTable As Range
Dim intCount As Integer
Dim celColl As Cells
Dim i As Integer
Dim rngLen As Integer
Dim bolWild As Boolean
Dim strWild As String
Dim strWildcard As String
Set tblOne = ActiveDocument.Tables(1)
intCount = tblOne.Columns(2).Cells.Count
Set celColl = tblOne.Columns(2).Cells
strWild = ""
For i = 1 To intCount
If i = 1 Then
i = i + 1
End If
Set celTable = ActiveDocument.Tables(1).Cell(Row:=i, Column:=2)
Set rngTable = ActiveDocument.Range(Start:=celTable.Range.Start, _
End:=celTable.Range.End - 1)
rngLen = Len(rngTable.Text)
bolWild = False
If (Mid(rngTable.Text, 1, 1) = "&") Then 'remember to replace & with asterisk!'
rngTable.SetRange Start:=rngTable.Start + 1, End:=rngTable.End
End If
If InStr(1, rngTable.Text, "&", vbTextCompare) > 0 Then 'remember to replace & with asterisk!'
strWildcard = rngTable.Text
rngTable.Text = Replace(rngTable.Text, "&", "", 1) 'remember to replace & with asterisk!'
bolWild = True
End If
If InStr(1, rngTable.Text, "-", vbTextCompare) > 0 Then
strWildcard = Replace(rngTable.Text, "-", "[.-]", 1)
bolWild = True
End If
If InStr(1, rngTable.Text, "?", vbTextCompare) > 0 Then
strWild = strWild + rngTable.Text + Chr$(13)
strWildcard = Replace(rngTable.Text, "?", "_", 1)
bolWild = True
End If
If (bolWild = False) Then
Dim oRng As Word.Range
Set oRng = ActiveDocument.Range
With oRng.Find
.ClearFormatting
.Text = strWildcard
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchFuzzy = False
.MatchWildcards = True
With .Replacement
.Text = rngTable.Text
.Font.Bold = True
.Font.Italic = True
End With
.Execute Replace:=wdReplaceAll
End With
End If
Next
' If bolWild = True Then'
' MsgBox ("Please search the following strings with - or ? manually:" + Chr$(13) + strWild)'
' End If'
End Sub
Maybe the LIKE statement could help you:
if "My House" like "* House" then
end if
Regular Expressions:
Searching for Search4 and replace it by SEARCH4 and using wildcards to achieve that:
Set objRegEx = CreateObject("vbscript.regexp")
objRegEx.Global = True
objRegEx.IgnoreCase = True
objRegEx.MultiLine = True
'here you can enter your search with wild cards
'mine says "S" followed by any character followed by "arch" followed by 1-n numbers.
objRegEx.Pattern = "S.arch([0-9]+)"
newText = objRegEx.Replace("Test Search4", "SEARCH$1")
MsgBox (newText)
'gives you: Test SEARCH4
More information how those wildcards to use can be found here
It might be hard in the beginning but I promise you will love it ;)
You can replace use to search for strings too:
Dim text As String
text = "Hello Search4 search3 sAarch2 search0 search"
Set objRegEx = CreateObject("vbscript.regexp")
objRegEx.Global = True
objRegEx.IgnoreCase = True
objRegEx.MultiLine = True
'here you can enter your search with wild cards
'mine says "S" followed by any character followed by "arch" followed by 1-n numbers.
objRegEx.Pattern = "S.arch[0-9]+"
If (objRegEx.test(text) = True) Then
Dim objMatch As Variant
Set objMatch = objRegEx.Execute(text) ' Execute search.
Dim wordStart As Long
Dim wordEnd As Long
Dim intIndex As Integer
For intIndex = 0 To objMatch.Count - 1
wordStart = objMatch(intIndex).FirstIndex
wordEnd = wordStart + Len(objMatch(intIndex))
MsgBox ("found " & objMatch(intIndex) & " position: " & wordStart & " - " & wordEnd)
Next
End If
The result for the variable text would be:
Search4 position: 6 - 13
Search3 position: 14- 21
...
So in your code you would use
rngTable.Text as text
and
rngTable.SetRange Start:=rngTable.Start + wordStart, End:=rngTable.Start + wordEnd
would be the range you want to set bold.
Sub AllBold()
Dim tblOne As Table
Dim celTable As Cell
Dim rngTable As Range
Dim intCount As Integer
Dim intMatch As Integer
Dim celColl As Cells
Dim i As Integer
Dim strRegex As String
Dim Match, Matches
Set tblOne = ActiveDocument.Tables(1)
intCount = tblOne.Columns(2).Cells.Count
Set celColl = tblOne.Columns(2).Cells
Set objRegEx = CreateObject("vbscript.regexp")
objRegEx.Global = True
objRegEx.IgnoreCase = True
objRegEx.MultiLine = True
For i = 1 To intCount
If i = 1 Then
i = i + 1
End If
Set celTable = ActiveDocument.Tables(1).Cell(Row:=i, Column:=2)
Set rngTable = ActiveDocument.Range(Start:=celTable.Range.Start, _
End:=celTable.Range.End - 1)
If rngTable.Text <> "" Then
strRegex = rngTable.Text
strRegex = Replace(strRegex, "*-", "[\w]{0,}[^\w]{0,1}[\w]{0,}", 1)
strRegex = Replace(strRegex, "*", "\w+", 1)
strRegex = Replace(strRegex, "-", "[^\w]{0,1}", 1)
strRegex = Replace(strRegex, "?", ".", 1)
objRegEx.Pattern = "\b" + strRegex + "\b"
Dim oRng As Word.Range
Set oRng = ActiveDocument.Range
Set Matches = objRegEx.Execute(ActiveDocument.Range.Text)
intMatch = Matches.Count
If intMatch >= 1 Then
rngTable.Bold = True
For Each Match In Matches
With oRng.Find
.ClearFormatting
.Text = Match.Value
With .Replacement
.Text = Match.Value
.Font.Bold = True
.Font.Italic = True
End With
.Execute Replace:=wdReplaceAll
End With
Next Match
End If
End If
Next i
End Sub