Extract value from Outlook email message custom field, and populate Excel - vba

I have designed an Outlook email form that holds several custom fields. One is "reference number", a free text box with the name "TextBox1":
I am trying to display the contents of that text box so I can later populate Excel, using this as a first step just to display the contents (doesn't work)...
MsgBox (msg.UserProperties.Find("TextBox1", Outlook.OlUserPropertyType.olText).Value)
Can anyone correct this line for me please? I want the message box to display "1234567".
Once I get that right, I can then copy the value into the Excel sheet.
Many thanks for your time.
Shane
(Wetherby, UK).
EDIT:
Here is more complete code showing the declaration and assignment of objects:
Dim rng As Excel.Range
Dim msg As Outlook.MailItem
Dim nmspace As Outlook.NameSpace
Dim folder As Outlook.MAPIFolder
Dim item As Object
Set nmspace = Application.GetNamespace("MAPI")
Set folder = nmspace.PickFolder
'Look at each email message in a folder
For Each item In folder.Items
intColumnCounter = 1
Set msg = item
intRowCounter = intRowCounter + 1
Set rng = wks.Cells(intRowCounter, intColumnCounter)
rng.Value = msg.To
...more items here to pick up sender address, subject, date sent, etc)...
MsgBox (msg.UserProperties.Find("TextBox1", Outlook.OlUserPropertyType.olText).Value)
'This is the field whose value I want to take for Excel
Next item
SECOND EDIT:
Here is a screen grab of the object's advanced properties:
It is a "normal" free text box entered into an email template. It's got the right name (TextBox1), and even has the right value (1234567). But somehow I cannot get the code to read the value of 1234567 and display it in the message box.
I'm stumped. it needs someone clever than me! Thank you to all who are pondering this one.

SOLVED!!! (Apologies for shouting).
Earlier replies got me thinking. I tried this line instead:
MsgBox (msg.UserProperties.Find("New - Study Number").Value)
as "New-Study Number" is what was used for the field name:
I think part of my problem was I was getting confused with the various usages (property name, field name, control name) and the VBA field properties boxes being a little unclear.
Nevertheless - thank you to all who contributed; I hope this helps others! 8)

Related

How to program a CATIA macro which searches a set of text through the drawing sheet and replace them

I'm currently trying to program a CATIA macro to search through a specific text:"DD/MM/YYY" on a 2D CATIA drawing sheet and replace that same text with a user inputted text. (Basically to update the text box)
I'm currently new to VBA scripting language and have zero to no experience in doing this. I've researched extensively on this but found no codes close to achieving the problems that I am trying to solve.
Textbox contents to be replaced by user
what I wanted the CATIA macro to do
I'm quite sure that your date text string has a specific name in the title block, so search for that specific text string name and assign another value.
If you have a lot of drawings to do this task, you can do it in batch mode, open one by one drawings in a folder, replace the date, save drawing, close document...no input from designer, just assign the new date value inside your new macro.
This short snippet will search all Texts entities and try to replace with a fixed string:
Sub Catmain()
Dim oDoc As Document
Dim oView as DrawingView
Dim oText As DrawingTexts
Dim txt_to_src As String
Dim txt_to_place As String
Dim n As Integer
n = 0
Set oDoc = CATIA.ActiveDocument
Set oSheets = oDoc.Sheets
Set oViews = oSheets.ActiveSheet.Views
Set oView = oViews.ActiveView
Set oTexts = oView.Texts
txt_to_src = "STACK OVERFLOW."
txt_to_place = "REPLACED"
For Each srcText In oTexts
If srcText.Text = txt_to_src Then
srcText.Text = txt_to_place
n = n + 1
End If
Next
MsgBox n & " text frames have been replaced"
End Sub
This only searches all texts in the active view of the active sheet of the opened document.
Consider to use a more specific check criteria such Instr (check if a string is contained into another string), the equality used is just a representative check.
You'll probably need to cycle all views of a Sheet (i.e. all Items of oViews collection), and all Sheets of a document (i.e. all items of oSheets collection). Then extend to cycle all opened DrawingDocuments if you want.
Remember that an empty document with a title block already has 2 Views (background and Main) so if your drawing has, say, just 1 Front View, the script has to cycle through 3 views.

Error 1004 with VBA code with bookmarks

I am using a macro to populate a word document with text from named ranges in excel. The word document has bookmarks that correspond with the named excel ranges. I did not write the code, but rather copied it from another source.
There is quite a bit more to this macro than the snippet I posted. I could post the rest if that is useful. I had about half of my word document bookmarked and the macro was working fine then it suddenly stopped working.
I am receiving a error 1004 in the line highlighted below. I am a newbie so I'm not even quite sure what I should be searching for to fix this issue. Any assistance you could provide would be appreciated! Thanks in advance!
P.S. In case it's relevant, I am using Word and Excel 2007
'PASTE TEXT STRINGS LOOP
n = 1
For Each temp In BkmTxt
p = p + 1
Prompt = "Please wait. Copying text. Carrying out operation " & p & " of " & pcount & "."
Application.StatusBar = Prompt
'If The Bkmtxt(n) is empty then go to the next one, once that has been found do next operation.
If BkmTxt(n) = Empty Then
n = n + 1
'should find match and work
Else
'You might want to use multiple copies of the same text string.
'In this case you need to call the bookmark as follows: "ARTextWhatever_01"
'You can use as many bookmarks as you want.
BkmTxtSplit = Split(BkmTxt(n), "_")
vValue = Range(BkmTxtSplit(0)).Text **<----- ERROR HERE**
Set wdRng = wdApp.ActiveDocument.Bookmarks(BkmTxt(n)).Range
If Len(sFormat) = 0 Then
'replace the bookmark text
wdRng.Text = vValue
Else
'replace the bookmark text with formatted text
wdRng.Text = Format(vValue, sFormat)
End If
'Re-add the Bookmark
wdRng.Bookmarks.Add BkmTxt(n), wdRng
n = n + 1
End If
Next
Step 1: Don't copy code from external sources. Use external sources as a learning tool and try to understand what they are actually doing.
Now if I understand you correctly, you simply have an Excel sheet with named ranges, I assume they have information already within them, and a word document with bookmarks that EXACTLY match the named ranges:
Step 2: Make sure you have the word object library reference within excel
Here:
sub KeepItDoin()
dim xlRange as Excel.Range
dim wdApp as new Word.Application
dim wdDoc as Word.Document
dim wdBkm as Word.Bookmark
set wdDoc = wdApp.Documents.Open( "Filepath" ) 'get filepath from where ever
for each wdBkm in wdDoc.Bookmarks
set xlRange = Application.Range(wdBkm.Name)
wdBkm.range.text = xlRange.Value
next wdBkm
end sub
That will get you close probably (didn't test, don't care if it works. Use it to learn). The idea is that if the bookmarks match up to the range, we can use their names to find the ranges in excel and then tell excel to move the data within it into the bookmarks range.
You will likely need to add some formatting or maybe create a table and then move cell by cell in the range and fill the table but this is as close as I'm willing to get since you like to copy pasta.
In case anyone is interested, I figured it out. There was an error with the bookmarks I inserted into my Word document. This macro returns Error 1004 if the word document contains a bookmark that does not correspond to a range in excel. Thank you for your help.

Populating a combobox in Word from Excel - stops working after Excel file is moved

Thanks for your time! Using snippets of code gathered here on stackoverflow and elsewhere, I was able to cobble together a macro that will populate a combobox in Word from a defined range of data in an Excel file, and then get a label to print the second column from the combobox (which is too long to display in the combobox itself). So far, so good. Here's my code:
Private Sub ComboBox1_DropButtonClick()
'Late binding. No reference to Excel Object required.
Dim xlApp As Object
Dim xlWB As Object
Dim xlWS As Object
Dim cRows As Long
Dim i As Long
Set xlApp = CreateObject("Excel.Application")
'Open the spreadsheet to get data
Set xlWB = xlApp.Workbooks.Open("EXCEL FILEPATH")
Set xlWS = xlWB.Worksheets(1)
cRows = xlWS.Range("$A2:$B216").Rows.Count - xlWS.Range("$A2:$B216").Row + 1
ComboBox1.ColumnCount = 2
'Populate the listbox.
With Me.ComboBox1
For i = 2 To cRows
'Use .AddItem property to add a new row for each record and populate column 0
.AddItem xlWS.Range("$A1:$B216").Cells(i, 1)
'Use .List method to populate the remaining columns
.List(.ListCount - 1, 1) = xlWS.Range("$A1:$B216").Cells(i, 2)
Next i
End With
'Clean up
Set xlWS = Nothing
Set xlWB = Nothing
xlApp.Quit
'Make label print column 2 of ComboBox
With ComboBox1
Label1.Caption = .List(.ListIndex, 1)
End With
End Sub
The problem is that when the Excel file is moved and then the Word file is closed and reopened, the comobobx no longer gets populated. Unfortunately, this needs to be a standalone Word doc that is distributable via e-mail to multiple users. Is there a way to populate the combobox so the Word document holds the data without having to refer back to the Excel file each time the doc is opened?
Thanks again!
One way to achieve this that I've used before is not to use Excel at all, when you send out the Word document, have it connect to a trusted web site that returns the list instead.
While I've not done this in Word, I have done it with Excel where the spreadsheet was emailed out as a blank template for filling in. A web site was used to populate reference data dropdowns. The reference data changed periodically so that was the best way to provide the freshest data while retaining an existing spreadsheet that people were familiar with.
If you are not too bothered about populating from a spreadsheet, you can of course, create a combo from code, the values for the combo could be kept in a field in Word.
Let me know if either of these is helpful & I will try to expand if needed.
Update:
You can make use of a DocProperty Field to store the entries for your combo if you don't actually need anything else from your spreadsheet.
Create a field called Combo Options or whatever and put into it:
Option 1;Option 2;Another Option
Or whatever text options you want.
In VBA, you can access the fields using:
ActiveDocument.CustomDocumentProperties("Combo Options").Value
Then you can split the field into it's components and iterate over them to add the combo box options.
Why don't you create file in user's computer with desired data? That means, it only requires first time for them to open excel file and afterwards it would read the data from .txt file.
Here is link on how to create simple file in user's computer:
http://www.java2s.com/Code/VBA-Excel-Access-Word/File-Path/WritingtoTextFilesUsingPrint.htm

Outlook Get Other Emails in Email Thread--UniqueBody

I am using VBA to format all outbound email messages in a certain way before sending. For example, I want to remove the first column from all tables which are embedded in the email. I use the following code:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim wd As Word.Document
Set wd = ActiveInspector.WordEditor
Dim tb As Word.Table
For Each tb In wd.Tables
tb.Columns(1).Delete
Next tb
End Sub
The above code works perfectly. However, the problem is that I only want to format my email text. Often, I will be responding to or forwarding someone else's email, which means that the text of the previous email will be in the same Inspector window. I don't want to format the text/images/etc. of the previous emails in the thread. How can this be achieved?
I know that each email within a thread--although they're all in the same window--is an individual unit. I know this because when reading an email which is part of a thread, as you move the mouse, you will see
on the right side of the screen, indicating where the next part of the thread is. When composing a new email (reply or forward) which is part of the thread, the above buttons are not shown, but you will still see a blue horizontal line separating the different parts of the thread from each other.
I was thinking that maybe I can search for the first occurrence of the line in the email, and only apply the formatting up until that point. However, it appears that the line isn't really text or any regular formatting which is searchable in the normal sense. In fact, if you copy the email text (before sending), and then paste into Word, the line disappears.
Any suggestions?
Thanks!
Update
My question has nothing to do with the "conversation view" found in versions 2010 and later.
Outlook 2010 allows you to view the other emails in the thread in one group. What I want, however, is to be able to loop through (via code) the emails in the thread within the same email. So, if there was an email "a", and then a reply, "b", and then another reply, "c", c will also contain b beneath it, and then a beneath that, all within the same email. In pseudo-code, I would want the following:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim wd As Word.Document
Dim smail as SubEmail
Dim tb As Word.Table
Set wd = ActiveInspector.WordEditor
For Each smail in wd
For Each tb In wd.Tables
tb.Columns(1).Delete
Next tb
Exit For
Next smail
End Sub
Update
I found a similar feature in Exchange Web Services, called UniqueBody. See here. That's exactly what I'm looking for, just not with Exchange.
Why not just look for "From:" chr(13) "Sent:" ? Outlook is going to put those tags in any email regardless of where it came from.
Assume that the entire body of emails a, b, c in your example above are in sBody:
Sub GetFirstThread()
Dim olItem As Outlook.MailItem
Dim sText As String
Set olItem = ActiveExplorer.Selection.Item(1)
sBody = olItem.Body
i=1
While i < Len(sBody)
If Asc(Mid(sBody, i, 1)) = 13 Then 'Look for From:
If Mid(sBody, i + 1, 5) = "From:" Then
'we found the start of email b
nPosEb = i
End If
End If
i=i+1
Wend
'...do something with nPosEb
End Sub

Find cell location based on value then do something- User Forms VBA Excel

i have experience in programing, however, I am new to VBA. I have a user form that i am working on. This form has a Combo Box that has a list initialized to it. What i am trying to do is:
*Get the ID Number value inputted by the user from the ComboBox
*Take the value inputted by the user and find its match using a range of values from a worksheet (i.e. Worksheet.Range("ID_Number_List"))
*Once it obtains it's match get the location of the cell that it matches
* Off set the location of the cell by one column to get the Name that relates to the ID Number(Same Row) to set it to textBoxName.Value
*Off set it two columns to get the telefone number that relates to the ID Number and set it to textboxTele.value
I want this to happen as soon as a value is selected from the Combobox, so my question is does my code go in the combo box or does it go to the next text box? so as soon as the person tabs over to the next text box the code is automatically execute. i would like the code to fully execute without tabing over to the next box.
This code is not complete but here is what i have (i didnt add the off set part i just did a test execution):
Dim ORIValue As String
'get value from combo_box Set
ORIValue = COMBO_ORILIST.Value
Dim cLoc As Range
Dim cORIVal As Range
'worksheet with the ID information Dim ORISheetList As Worksheet
Set ORISheetList = Worksheets("ORI_LIST")
'
For Each cLoc In ORISheetList.Range("ORI_LIST")
'compare the input string from list- considering using Match function for this
If StrComp(cLoc, ORIValue, vbTextCompare) Then TextBAgencyName.Value = "test"
Else: Next cLoc
End If
Let me know what you think. If i have to rewrite everything i will.
Your code doesn't compile.
If you have a userform with a single combobox called ComboBox1, you need to put your cell-finding code in the form code as follows:
Private Sub ComboBox1_Change()
MsgBox "yep, this is where the code should go"
End Sub
I suspect using the rowsource property of the combobox in combination with the index of the selected value you probably don't need to actually perform a search for the selected value. Something like this might work:
Private Sub ComboBox1_Change()
MsgBox Range(ComboBox1.RowSource).Cells(ComboBox1.ListIndex + 1)
End Sub
Hope that helps.