Script to modify outlook (2003) contacts - formatting

I'm trying to clean up my outlook 2003 contacts, which has become a rather ugly mess of various formatting, etc.
Basically, I have a bunch of contacts, in the form of either:
0xxxxxxxxx [ten digits, starting with 0] 0xxxxxxxx [nine digits, starting with 0] 0xxxxxxxx (xxxxx) [the same nine digits above with the last five repeated in parentheses] +xxxxxxx [some random "complete" number with an international dialing code, etc]
I want all of the numbers to match the last format. The algorithm is simple enough: for the first two types, drop the 0 and add +YYY where YYY is my country code. Ditto for the third, but drop everything in parentheses.
My problem is that I don't know how to go about doing this. I've written a million scripts in my life in Perl, but I'd rather not export everything to text, process it, and re-import; I'd like to have a one-click solution that can easily be re-run (such as when I import a new contact from my companies' directory which comes in one of the forms above). I suspect that VBScript is the way to go; I've seen a few references online to accessing contacts as objects, but I'm not really sure what the best way to get started is.
Any recommended resources?
This is a duplicate of https://superuser.com/questions/15913/script-to-modify-outlook-2003-contacts ; I'm not sure which site is a better location

I would say VBA, rather than VBScript.
Sub GetContactsTel()
Set oFolder = GetNamespace("MAPI").GetDefaultFolder(olFolderContacts)
' Loop through all of the items in the folder.
For i = 1 To oFolder.Items.Count
Debug.Print oFolder.Items(i).BusinessTelephoneNumber
Next
End Sub

Related

Mysterious Black Lines in Word When Using In-House VB.Net Application

A little backstory. I work at an organization that uses Mail Merge and SQL Databases to populate letters with names/addresses. Those letters are sent out to our donors as thank yous. These letters change frequently, and new ones come up at least 10 times a month.
To simplify our process, I created a program that allows you to copy/paste the letter body content into rich text boxes and when you press the 'Go' button, it opens a pre-made Word template and replaces bookmarks in the template with the copied body content.
The program works great with most letters, but some of them have a problem where these thick black lines are created and I'm unable to do ANYTHING to remove them. I can't right click them, I can't delete them with Backspace or Delete, and I can't highlight them.
I'm thinking that the problem may come from hidden formatting. Some of the employees that write the letters are using the Mac version of Office 2016, and I'm using Windows version. I sent an RTF file that showed the black lines for me to someone who uses the Mac version, and they said they couldn't see the lines.
My question is, is there a way to get rid of these lines or prevent them in the future? I've thought about upgrading Office version to 2019 on both ends, but there are quite a few people that have their hands in these letters and it may be difficult to upgrade everyone.
Please refer to the attached image for visual reference. Names and personal details have been removed.
EDIT: Here is the 'Go' code:
'create temp rtf files to maintain rtf
If strForm = "ANG2" Then
txtPreD.SaveFile("\\server\AcknowledgementLetters\fptemp.rtf")
txtPostD.SaveFile("\\server\AcknowledgementLetters\bptemp.rtf")
ElseIf strForm = "ANGL" Then
txtPreD.SaveFile("\\server\AcknowledgementLetters\predtemp.rtf")
txtPostD.SaveFile("\\server\AcknowledgementLetters\postdtemp.rtf")
txtBP.SaveFile("\\server\AcknowledgementLetters\bptemp.rtf")
Else
txtPreD.SaveFile("\\server\AcknowledgementLetters\predtemp.rtf")
txtPostD.SaveFile("\\server\AcknowledgementLetters\postdtemp.rtf")
End If
'if bookmarks exists, insert appropriate rtf files
If odoc.Bookmarks.Exists("fp") = True Then
goWord.ActiveDocument.Bookmarks("fp").Select()
goWord.Selection.InsertFile(FileName:="\\server\AcknowledgementLetters\fptemp.rtf")
End If
If odoc.Bookmarks.Exists("bp") = True Then
goWord.ActiveDocument.Bookmarks("bp").Select()
goWord.Selection.InsertFile(FileName:="\\server\AcknowledgementLetters\bptemp.rtf")
End If
If odoc.Bookmarks.Exists("PreD") = True Then
goWord.ActiveDocument.Bookmarks("PreD").Select()
goWord.Selection.InsertFile(FileName:="\\server\AcknowledgementLetters\predtemp.rtf")
End If
If odoc.Bookmarks.Exists("PostD") = True Then
goWord.ActiveDocument.Bookmarks("PostD").Select()
goWord.Selection.InsertFile(FileName:="\\server\AcknowledgementLetters\postdtemp.rtf")
End If
Before this happens, the program checks to see which template it needs to open and opens it as a Word object (odoc). This bit of code is really the only important part. After this, I just click Finish it just saves the file once I'm done checking it for errors. Also, yes, the RTF files that it creates DO have the black lines as well. Here is another picture of the program itself just so you can get a better idea of what's going on.

VBA getcrossreferenceitems(wdRefTypeNumberedItem) Paragraph Cut Off?

I'm using excel vba to extract information from a word document.
In the word document, there are levels of numbered lists. For example:
1. ABC
1.1 DEF
1.1.1 ABCDEF
2. AAA
2.1 BBB
2.1.1. CCC
and I need to get the full context of each heading in each level and put them into an excel range, i.e. {"1.ABC", "1.1 DEF", "1.1.1 ABCDEF", "2. AAA", "2.1 BBB", "2.1.1. CCC"}
The function I use is:
For Each sec In objDoc.getcrossreferenceitems(wdRefTypeNumberedItem)
However, my headings are truncated if the headings are too long. For example, I have (random text is added for confidentiality reasons):
"5.2.11. Current References: As part of the evaluation process, XXX will conduct 2340AERTQ3493YR. When selecting ADT34534FDGSR, please ensure that they are AERA34AEFDS."
But only
5.2.11. Current References: As part of the evaluation process, XXX will conduct 234
is displayed, and the rest of the sentence is gone.
If anybody has an alternate solution, please let me know.
i confirm this behavior. A workeable albeit and elaborate solution is to scan the document for all numbered items which gives you the full text and then cross reference that result against the list returned by the GetCrossReferenceItems. There's quite some work involved but works and gives you the ability to create one list with referable Headings and NumberedItems, which is what I did to build a more user friendly alternative to Word's own implementation.
You'll have to match the formatting Word applies to the list returned by GetCrossReferenceItems, ie. the identation and removal of special characters.
Be careful with track changes. There is a bug in GetCrossReferenceItems which means that items (in my case headers) that have a tracked change at the beginning of the text are not returned by GetCrossReferenceItems but internally are still on the list so the index is offset. If the item in question is item 11, then GetCrossReferenceItems gives the item belonging to item 12 the item 11. A workaround is to accept all revisions before GetCrossReferenceItems and undo it after.
It's not easy but works.
I met a similar problem in MSWord. I found some paragraph's text are shorten in the following code
Sub bug()
items = ActiveDocument.GetCrossReferenceItems(wdRefTypeNumberedItem)
For idx = 1 To UBound(items)
MsgBox items(idx)
Next
End Sub
I have to use a some long solution( in Python, sorry. But is is easy to rewrite in VBA):
varHeadings = []
for par in objDoc.Paragraph:
if par.Range.ListFormat.ListType == win32com.client.constants.wdListOutlineNumbering:
idx = par.Range.ListFormat.ListString
txt = par.Range.Text.strip('\n').strip('\r')
varHeadings.append('%s%s' % (idx, par.Range.Text))
which does work. However, as I have said, it is some tedious. So did I miss some VBA function in MSWord, or GetCrossReferenceItems has known bug and can not found any replacement in VBA?

Working with multiple discontinuous selection

I'm trying to do something with a multiple selection. I wanna add some text before every selected paragraph but, when I select multiple discontinuous paragraphs, if I do Selection.Paragraphs.Count I always get "1".
How could I work with all paragraphs apart?
Example:
Paragraph1(Selected first)
Paragraph2
Paragraph3(Selected second)
What I got when I try to add some text at the beginning of these paragraphs:
Paragraph1
Paragraph2
TEXTParagraph3
What I really want to obtain:
TEXTParagraph1
Paragraph2
TEXTParagraph3
I'm working like this:
sub x()
dim p as paragraph
for each p in selection.paragraphs
p.range.insertbefore("TEXT")
next
End sub
Word simply cannot do what you'd like for it to do. Developers have wished for this since multiple selections were introduced in 2003 (I think it was, might have been version 2007). Word's object model simply does not support it.
If this is something you want to provide to the user to make life easier you'll need to give the tool a way to mark the paragraphs so your code can recognize them. You could provide a macro, for example, that assigns an incrementing bookmark name to each selection (the user selects, then runs your macro; repeat for each paragraph). Your code can then address each bookmark and perform the actions. To make this more user friendly you can assign the macro to a keyboard shortcut and/or a button in the Ribbon/QAT and/or the right-click menu.

Formatting issues duplicating table

Forward
I am making a "label program" that will print waybill information. Consists of a table in Word on a custom 3x5 inch document with 0 margins.
I currently have a simple form that, if you need copies, it will edit one of the cells so that each time it prints the "pieces count" is incremented. 1of10, 2of10, 3of10.....
While that worked the code submitted a separate print job for each "label". That created a problem for the end user where they would have to wait about 5-10 seconds between print jobs. When printing a couple of hundred of these at a time those seconds can add up.
Corrective solution
To try an alleviate this problem I wanted to make copies of the table so that 100 labels would be printed as one 100 page document. Found several solutions for copying pages of text but I have tables which complicated things. The closest solution I have found was:
With ActiveDocument
.Tables(1).Range.Copy
.Range.Select
'.Range.InsertAfter (Chr(11))
Selection.Collapse wdCollapseEnd
Selection.Paste
End With
And this does make a perfect copy of the table however it is merging the tables together. So if I wanted to loop this to create several more labels it would be doubling up the results every time since the code above just copies the first tabel.
To try and fix that issue I added a line break (vertical tab) before the paste. You will see that as the commented out line in the above snippet. This breaks up the tables but adds too much whitespace in between.
Page breaks seems like the solution here. While those did make the table break up they ended up creating a blank page in between each label which I was having enough of a time clearing from the GUI let alone in VBA.
The actual question
How can I take a table that is perfectly designed to fit on one 3x5 inch page and duplicate it X times. The caveat is I need to be able to find the cell programically that contains the pieces text. Currently I can use these absolute reference for the first table
ActiveDocument.Tables(1).Cell(5, 1).Range.Text
So if I had 3 tables for instance I need to be able to call each table and edit the text of the Cell(5, 1).
In case you ask
I know this functionality is better placed inside actual label programs like Bartender but those cost money that the company will not allocate for the only label my company uses.
The right concept was there. We needed to add a break in between the tables to disassociate them. Adding the vertical tab Chr(11) was obviously not the correct way to do it.
A proper section break would be the route to go here. Looking at MSDN you can see there are multiple types of section breaks. After testing a desirable outcome was acheived from using wdSectionBreakNextPage which is a "Section break on next page."
Basically just needed to add one line to the above code.
With ActiveDocument
.Tables(1).Range.Copy
.Range.Select
End With
With Selection
.Collapse wdCollapseEnd
.InsertBreak (wdSectionBreakNextPage)
.Paste
End With
I hate the use of Selection and I am going to look into that but for now this does function properly.
Since the tables are not single units we are able to query .Tables in order to edit each page individually.

Word VBA - Load part of doc into variable, and run .indexOf to search

Okay, I am a Javascript programmer and VBA is driving me insane - I know nothing about it and it is like pulling teeth to find simple documentation on the simplest thing.
I'm literally trying to run a little script to auto-format a document, partly based in content.
I want to grab the third line of document, or first 100 characters, I really don't care, and run the equivalent of String().indexOf('foobar') on it, to check if that part of the document contains a string.
I cannot for the life of me find how to:
a. Load text selection into a variable.
b. Run a sane semblance to indexOf.
Can someone please help? And maybe point me to a sane VBA documentation that is not Micrsoft?
a. Load text selection into a variable.
Identify a range (Word.Range) you want and get the Text property of that range.
For instance,
dim s as string
s = ThisDocument.Paragraphs(3).Range.Text
b. Run a sane semblance to indexOf.
Is InStr no good?
msgbox InStr(s, "foobar")