VBA - Word change the concept of word(a.b is one word or two) - vba

I have a question: i want to have an array of words of a WORD document, which are larger than 29 and Shorter than 40 characters. I implemented it in VBA this way:
Sub function()
Dim arr(1000) As String
counter = 0
For Each sentence In ActiveDocument.StoryRanges
For Each w In sentence.Words
If Len(w) > 28 And Len(w) < 40 Then
arr(counter) = w
counter = counter + 1
End If
Next
Next
End Sub
The Problem is that I want all words with char '_' cosidered as one word; for example: 'Adrian_link_mart' is one word and not 3: 'Adrian' and 'link' and 'mart' like it will be considered
thanks for your help, adrian

This may help. There is a bit of a wrinkle as you will see below.
Option explicit
Sub test()
' Use a collection rather than an array as we don't need
' to know the size in advance
Dim word_array As Collection
' Word doesn't actually have a 'word' object. Probably because
' that clashes with Word the application. So instead of Word.Word
' we are using word.range which gives us all the utility we will
' need
Dim my_word_range As Word.Range
Dim my_range As Word.Range
For Each my_range In ActiveDocument.StoryRanges
For Each my_word_range In my_range.Words
With my_word_range
Do While .Next(unit:=wdCharacter) = "_"
' '_' is considered to be a word by Word so we need to
' count two Word words to get to the end of the next
' text word IYSWIM
.MoveEnd unit:=wdWord, Count:=2
Loop
If .Characters.Count > 28 And .Characters.Count < 40 Then
word_array.Add Item:=.Text
End If
End With
Next
Next
End Sub
If you are new to VBA then
Include Option explicit at the top of every module
In the VBA IDE go Tools.Option.Editor.Code Settings and make sure every box is ticked.
Learn how to use F1. In the VBA IDE, putting the cursor on a keyword and pressing F1 will bring up the MS help page for that keyword

Related

Why is my VBA macro only splitting the 1st and 3rd parts of a Word document?

I have a macro which takes one Word document, copies the data inside my parameters then pastes it multiple separate documents (in this case three).
This is the first time using VBA, so please go easy.
The original document is a long document, which has multiple repeating sections. By filling in the original document, the user can save time completing one rather than three near identical documents. I have split the original into three sections. My code takes the data from the first declared section and pastes it into a new document. It also works for the third. The second, however does not work.
The
With R.Find
.Text = "START OF FORM*^12"
.MatchWildcards = True
section looks for the text 'Start of Form' and takes that and the rest of the contents up until '^12' (which I believe refers to a page break).
The document is set out so that each section of the document starts with that text and finishes with page break.
Sub DocSplit()
' Declares variable (in this case R).
Dim R As Range
' Sets R to the active document, being a number of ranges (will be defined later).
Set R = ActiveDocument.Range.Duplicate
' You won't be able to see what the macro is doing, but will run quicker.
Application.ScreenUpdating = False
' For R, find text with whatever is in the " marks.
With R.Find
.Text = "START OF FORM*^12"
.MatchWildcards = True
' Runs a series of statements as long as given conditions are true. While it's doing this,
While .Execute
' Copy and saves contents of R.
CopyAndSave R
' While ends.
Wend
'With ends.
End With
' Collapses range to the ending point.
R.Collapse wdCollapseEnd
' Returns or sets the ending character position of a range.
R.End = R.Parent.Range.End
CopyAndSave R
End Sub
Static Sub CopyAndSave(R As Range)
' Declares D as document.
Dim D As Document
' Represents the number of words in the collection.
' Long is a datatype for values too large for "integer".
Dim Count As Long
Count = Count + 1
' Copies R from previous Sub to a new document.
R.Copy
Set D = Documents.Add
' Pastes range, preserving original formatting.
D.Range.PasteAndFormat wdFormatOriginalFormatting
D.SaveAs R.Parent.Path & Application.PathSeparator & _
"F00" & Count, wdFormatDocument
D.Close
End Sub
I did expect three documents, F001, F002 and F003 to be created. I get two files, one containing the first section (as intended) and one file containing the last two.
I took a quick look at your code and I found these errors:
If you want the counter to increment each time the function is called, you must declare it in the main function, otherwise it will lose memory each time it's called.
R.Find needs an argument. If you want more details, look at here
R.End needs an argument, here you'll find some hints, depending on what you need to do.
I've updated some parts of your code to help you:
Sub DocSplit()
' Declares variable (in this case R).
Dim R As Range
' Represents the number of words in the collection.
' Long is a datatype for values too large for "integer".
Dim count As Long
count = 0
' Sets R to the active document, being a number of ranges (will be defined later).
Set R = ActiveDocument.Range.Duplicate
' You won't be able to see what the macro is doing, but will run quicker.
Application.ScreenUpdating = False
' For R, find text with whatever is in the " marks.
With R.Find("Text your're searching")
.Text = "START OF FORM*^12"
.MatchWildcards = True
' Runs a series of statements as long as given conditions are true. While it's doing this,
While .Execute
' Copy and saves contents of R.
Call CopyAndSave(R, count)
' While ends.
Wend
'With ends.
End With
' Collapses range to the ending point.
R.Collapse wdCollapseEnd
' Returns or sets the ending character position of a range.
R.End = R.Parent.Range.End
Call CopyAndSave(R)
End Sub
Static Sub CopyAndSave(R As Range, count As Long)
' Declares D as document.
Dim D As Document
count = count + 1
' Copies R from previous Sub to a new document.
R.Copy
Set D = Documents.Add
' Pastes range, preserving original formatting.
D.Range.PasteAndFormat wdFormatOriginalFormatting
D.SaveAs R.Parent.Path & Application.PathSeparator & _
"F00" & count, wdFormatDocument
D.Close
End Sub
If you have any doubts, don't hesitate to ask.

Find each word marked as error

Is it possible to find words that MS-Word marks as errors?
My goal is to find words containing "è" instead of "é", but to use a macro I need to replace the char only into words marked as error.
I'm working on MS-Word 2013
here is some code to get you started. you need to add code that checks for the "bad" letter
' this is just demo code that shows how misspelled words could be replaced
' create document with a few words, one or two misspelled
' then single-step this code using F8 key
' while watching the text in the document
Sub aaaaaa()
Dim i As Integer
Dim badChr As String
Dim badWrd As String
Dim wrd As Object
For Each wrd In ActiveDocument.Words
If wrd.SpellingErrors.Count > 0 Then
badWrd = wrd.SpellingErrors(1).Text
Debug.Print badWrd
wrd.SpellingErrors(1).Text = string(len(badWrd),"x") ' replace whole word if you like
wrd.SpellingErrors(1).Text = badWrd ' put back original
For i = 1 To wrd.SpellingErrors(1).Characters.Count ' loop characters in misspelled word
badChr = wrd.SpellingErrors(1).Characters(i).Text
wrd.SpellingErrors(1).Characters(i).Text = "x" ' replace character
wrd.SpellingErrors(1).Characters(i).Text = badChr ' restore character
Next i
End If
Next wrd
End Sub

insert missing period at end of paragraph in word

i receive reports (word document in .doc format ) from clients which due to some processes at their end are missing periods () at the end of most paragraphs. I have to manually add periods. Is there any code in word vba macros to accomplish this.
Thank you.
This is a fairly simple example on how to add a period to every paragraph that contains text. You could extend it to see if the paragraph really has no period at the end but I leave that up to you to decide.
Call the Macro from the Developer Tab after you added the macro:
Sub TestAddPeriod()
Dim oPara As Word.Paragraph
Dim rng As Range
Dim text As String
For Each oPara In ActiveDocument.Paragraphs
If Len(oPara.Range.text) > 1 Then
Set rng = ActiveDocument.Range(oPara.Range.Start, oPara.Range.End - 1)
rng.InsertAfter "."
End If
Next
End Sub

Counting how many comments and how they are distributed in VBA code?

I am looking to create some metrics about the quality of the VBA code I am writing, through different ratios of the actual code written and comment lines written.
Ideally I am looking for a VBA script/function to detect the comment lines in Macro Enabled workbooks and Excel add-ins and being able to differentiate where the comments and code are written e.g. have the comment to code ratio for each module and form in a project.
Below is the code I have so far, but I only managed to found how to give the total count of the lines and the count for the declaration lines. Is there something similar for comments?
Public Sub moduleInfo()
Dim objModule As Object
For Each objModule In Application.VBE.ActiveVBProject.VBComponents
With objModule
Debug.Print .Name, .CodeModule.CountOfLines, .CodeModule.CountOfDeclarationLines
End With
Next objModule
End Sub
You can check the existence of the character ' to spot a comment line. The comment ,ight occur anywhere in the code, such as after the instruction (you can easily modify the code if you want to count only lines that are purely comments). You can also count blank lines, because the CountOfLines property includes these.
Public Sub moduleInfo()
Dim comp As VBComponent, m As CodeModule
Debug.Print "Module", , "Lines", "Declarations", "Blanks", "Comments"
For Each comp In Application.VBE.ActiveVBProject.VBComponents
Set m = comp.CodeModule
Dim comments As Integer, blanks As Integer, i As Integer, line As String
For i = 1 To m.CountOfLines
line = Trim(m.Lines(i, 1))
If Len(line) = 0 Then
blanks = blanks + 1
ElseIf InStr(line, Chr(39)) Then
comments = comments + 1
End If
Next
Debug.Print m.Name, , m.CountOfLines, m.CountOfDeclarationLines, blanks, comments
Next
End Sub

better method for accenting every word in Word document?

I am new to programming, but I am trying to adapt an existing script as a MS Word 2010/2013 addin to add correct stress accentuation to every Latin word in an open document.
The script "DoAccentuate" returns an accented word for any unaccented Latin word I send it as a string. I just need help doing a better job of looping through all the words, and then stopping the loop when the last word is reached. My current method is a bit goofy...I insert a nonesense word at the end of the document and then loop until it gets selected and accented.
Perhaps there's a better or more efficient way to go about the whole thing.
Public Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Dim document As Word.Document
document = Globals.ThisAddIn.Application.ActiveDocument
Dim mySelection = document.Application.Selection
'make sure cursor is at start of document
document.Application.Selection.HomeKey(Unit:=Microsoft.Office.Interop.Word.WdUnits.wdStory)
'insert fake word at end to stop the loop
Dim range As Word.Range
range = document.Range()
range.InsertAfter(" documentendatoris")
Do
'use MS Word's wildcard to select the first individual word as trimmed string
mySelection.Find.Text = "<*>"
mySelection.Find.MatchWildcards = True
mySelection.Find.Execute()
'replace the selected word that has been found with its accented counterpart
mySelection.Text = Accentuate.Accentuate.DoAccentuate(mySelection.Text)
Loop Until mySelection.Text = "documentendatóris"
End Sub
Well, I don't realy know if its more efficient way but you could use document.Content and range.Words collection to check all words in main story range
document = Globals.ThisAddIn.Application.ActiveDocument
Dim range As Word.Range
range = document.Content
Dim current As Integer
current = 0
Dim words As Word.Words
words = range.Words
Dim word As Word.Range
Do
current = current + 1
If current < words.Count Then
word = words(current)
If word.Text.EndsWith(" ") Then
word.Text = word.Text.Trim() + "'s "
'replace the selected word that has been found with its accented counterpart
'mySelection.Text = Accentuate.Accentuate.DoAccentuate(mySelection.Text)
Else
word.Text = word.Text.Trim() + "'s"
End If
End If
Loop Until current = words.Count