Count selected lines in MS Word - vba

I wanted to count the lines of selected text in MS word document. I come up with code:
Sub Count_Lines()
ActiveDocument.ComputeStatistics (wdStatisticLines)
MsgBox ("The document contains " & NumLines & " Lines")
End sub
But it actually count the line of whole document.
Can anybody help, finding code which could count selected line only?

Just use Selection.Range object instead of ActiveDocument
Sub Count_Lines()
MsgBox ("The selection contains " & Selection.Range.ComputeStatistics(wdStatisticLines) & " Lines")
End Sub

Your code intends to show the value of NumLines in the message box. However, no value was assigned to that variable. In fact the variable itself was also not declared. The code below fills these two shortcomings and then works just fine. However, it will count all the lines in the document. If you just want the selected lines use the solution offered below.
Option Explicit
Sub Count_Lines()
Dim NumLines As Long
NumLines = ActiveDocument.ComputeStatistics(wdStatisticLines)
MsgBox ("The document contains " & NumLines & " Lines")
End Sub
NB. They say, Option Explicit "forces" you to declare variables which forces the reaction to resist. Compare the force with that of the traffic police who insist on your driving on the right side of the road. Using Option Explicit will not prolong your life but it will drastically reduce the amount of time you spend chasing stupid errors because you are too proud to let your computer point them out to you. Option Explicit was the tool that provided me with an immediate pointer to the source of the problem you are seeking help on here.

Related

'selection.footnotes.count' versus 'for each footnote in selection.footnotes'

I want to make some modification to the footnotes in a selected portion of a MS Word document. I would like to use a 'for each footnote in selection.footnotes', but this does not work. It returns all the footnotes in the document. I do not understand why, because if I run a 'selection.footnotes.count' this returns only the footnotes in the selected portion, which is what I want.
See this code, which can be used for testing the problem.
For example: type a number of lines in Word, insert some footnotes in each line, select one of the lines and run this code to see the difference.
Does anyone know what is wrong with my use of the For each footnote ...' statement?
For Each Footnote In Selection.Footnotes
i = i + 1
Next Footnote
MsgBox "• For ... Next: " & i & Chr(13) & _
"• Count: " & Selection.Footnotes.Count, vbOKOnly, "Number of footnotes in selection, counted using:"
I can reproduce what you describe, with the Range as well as the Selection object. I don't know "why"; it makes no sense as far as the object model goes. Sometimes, weird things happen with Selection, but that it also happens with Range...
I'd class it as a bug, but I don't have any confirmation to that effect from Microsoft.
This works, though
For ftCounter = 1 To rng.Footnotes.Count
Set ft = rng.Footnotes(ftCounter)
'Debug.Print ft.Range.Text
Next

Button to add column?

In excel 2013 I was hoping if someone can make a code for adding 1 blank column to a spreadsheet based on the user input after they click this button that is an activex control. The column will end based on how many rows there are in my table, meaning if there are 10 rows I should not see a column on line 11 of the spreadsheet.
I keep getting an error saying application defined or object error after I put in the column I want to add, I even tried both caps an lowercase and the same error comes up.
Private Sub CommandButton2_Click()
Dim x As String
x = InputBox("Enter a column that you want to add: ", "What column?")
If x = "" Then Exit Sub
ColumnNum = x
Columns(ColumnNum & ":" & ColumnNum).Insert shift:=xlShiftRight
Columns(ColumnNum - 1 & ":" & ColumnNum - 1).Copy Range("A1" & ColumnNum)
Columns(ColumnNum & ":" & ColumnNum).ClearContents
End Sub
This will get you started:
Dim x As Variant
Dim ColumnNum%
x = InputBox("Enter a column that you want to add: ", "What column?")
If x = "" Then Exit Sub
ColumnNum = x
ThisWorkbook.Sheets("Sheet1").Columns(ColumnNum).Insert shift:=xlRight
ThisWorkbook.Sheets("Sheet1").Columns(ColumnNum - 1).Copy
'THe line above doesnt make any sense whatsoever.
'Im not going to try and trouble shoot it but it seems like you dont understand how to
' properly scuplt things. Youll notice i changed how you strucutred the .copy part.
'THe part that doesnt make sense to me is the Range section.
ThisWorkbook.Sheets("Sheet1").Columns(ColumnNum).ClearContents
There were a few things wrong with your code.
You need to put Option Explicit at the top of your code. You didnt declare your variables.
you inpout box needs to be declared as variant
When i played around with this its clear you didnt fully reference what columns in what sheets need to be inserted. Notice my "ThisWorkbook....."
Your if statement is structured incorrectly as well.
I suggest you spend some time reading up on the basics some more :)

Excel VBA Self-Destruct Switch

I have had my first "Client-took-my-work-and-then-ghosted-me-without-paying" experience. For the future, I want to put in a killswitch, disguised as a regular macro, which makes the whole thing unusable. That way, even if they hire someone to crack the password and remove my "Your trial has expired..." check, a normal-looking macro (Something like "Fix_Sheet_Formatting") would be easily overlooked and run, destroying everything and saving the changes.
However, that leaves the VBA... We're talking a full purge here, so everything must go. I'll figure out how to do all of this on my own, I just don't want to waste time pursuing something that isn't possible:
Can VBA code delete itself from a workbook while running or does it have to be deleted from a macro on another workbook? And would deleting the code cause the macro to stop running, or can I have it delete everything except a nasty MsgBox after everything is done?
I'll leave the comments to debating whether or not this is a good idea (IMHO it probably isn't). As to the question itself, of course it's possible, and won't interrupt macro execution:
Public Sub Example()
Dim proj As Object
Set proj = ThisWorkbook.VBProject
Dim comp As Object
For Each comp In proj.VBComponents
With comp.CodeModule
.DeleteLines 1, .CountOfLines
If comp.Name = "ThisWorkbook" Then
.InsertLines 1, "Private Sub Workbook_Open()" & vbCrLf & _
vbTab & "MsgBox ""Where's my money, ##$%&!?""" & vbCrLf & _
"End Sub"
End If
End With
Next
ThisWorkbook.Save
End Sub
Obfuscation is an exercise for the reader.
Put a loop with due date as your payment data . Inside write code to get macro into infinity loop or to delete code.
If payment happens on time then just comment above piece of code or else just wait client come back to you on next day defined in loop.

How do I find the time of last typed word in Microsoft Word?

In Excel, you can find out when the last entry was made in a particular cell using VBA coding.
I was wondering whether in Word you can do the same as well.
I particularly want to know the time and date it was last entered.
In Word, you can't get the time a particular Word was entered into the document. What you can get is the last time the file has been saved:
Sub PrintLastSaveTime()
Dim propLastSaved As DocumentProperty
Dim propLastAuthor As DocumentProperty
Set propLastSaved = ActiveDocument.BuiltInDocumentProperties(WdBuiltInProperty.wdPropertyTimeLastSaved)
Set propLastAuthor = ActiveDocument.BuiltInDocumentProperties(WdBuiltInProperty.wdPropertyLastAuthor)
Debug.Print "The document was last saved by " & propLastAuthor.Value & " at "; propLastSaved.Value
End Sub

VBA Refactoring, MsgBox everywhere

I'm very reluctant to post this as I'm not looking for anyone to write code, rather to get me moving in the right direction here.
I have inherited a huge mass of VBA. I've rewritten an awful lot of it, but I've hit a wall here.
Basically the code checks through millions of lines of an external file, and checks character by character for certain values. However, the code displays a message box MsgBox for EVERY single value.
Here is an example:
If CharArray(1) = "S" & CharArray(2) = "SO" Then
MsgBox "Hello Stack Overflow"
Else: MsgBox "Hello somewhere else"
EndIf
And it goes on like this, thousands of times. I will refactor the endless If statements myself. Is there anything I can do to save this? I was going to just comment out manually any MsgBox that isn't displaying an error, but it's still potentially a mess.
Can I write to a cell with the data, and increment to the next row easily from my own Sub or Function to just do a replace of MsgBox with something else? That is to say write Sub ReplaceMsgBoxes() have it write to a current row, whatever the message box was going to write, and go on a line?
Questions:
Would this Sub need a global counter variable (for the Row to write to)?
Is there a commonly used method by programmers to get around this kind of mess?
If I write a Sub to replace this can I call the same way, i.e.
ReplaceMsgBox "Whatever the text for the MsgBox was to begin with"
Many thanks.
One easy way is to buffer the material into a string and then do a single MsgBoxSay we want to find all the dog in A1 thru A100
Sub FindDog()
Dim dog As String, msg As String
dog = "dog"
msg = ""
For i = 1 To 100
If Cells(i, 1).Value = dog Then
msg = msg & vbCrLf & Cells(i, 1).Address(0, 0)
End If
Next i
MsgBox msg
End Sub
If there were very many items, I would use a scrollable ListBox instead.
To write to a cell:
activecell = "what ever you want to say"
to advance to the next cell (below)
activecell.offset(1,0).select