A an alternative to the macro suggested in my comment, you may find the one below more convenient. Add something like:
Debug.Print "=====Text====="
Debug.Print TidyTextForDspl(.Body)
Debug.Print "=====Html====="
Debug.Print TidyTextForDspl(.HTMLBody)
Debug.Print "=====End====="
to your existing macro.
Public Function TidyTextForDspl(ByVal Text As String) As String
' Tidy Text for dsplay by replacing white space with visible strings:
' Replace spaces by {s} or {n s}
' Replace line feed by {lf} or {n lf}
' Replace carriage return by {cr} or {n cr}
' Replace tab by {tb} or {n tb}
' Replace non-break space by {nbs} or {n nbs}
' Where n is a count if the character repeats
' 15Mar16 Coded
Dim InsStr As String
Dim InxWsChar As Long
Dim NumWsChar As Long
Dim PosWsChar As Long
Dim RetnVal As String
Dim WsCharCrnt As Variant
Dim WsCharValue As Variant
Dim WsCharDspl As Variant
WsCharValue = Array(" ", vbLf, vbCr, vbTab, Chr(160))
WsCharDspl = Array("s", "lf", "cr", "tb", "nbs")
RetnVal = Text
For InxWsChar = LBound(WsCharValue) To UBound(WsCharValue)
Do While True
PosWsChar = InStr(1, RetnVal, WsCharValue(InxWsChar))
If PosWsChar = 0 Then
Exit Do
End If
NumWsChar = 1
Do While Mid(RetnVal, PosWsChar + NumWsChar, 1) = WsCharValue(InxWsChar)
NumWsChar = NumWsChar + 1
Loop
If NumWsChar = 1 Then
InsStr = "{" & WsCharDspl(InxWsChar) & "}"
Else
InsStr = "{" & NumWsChar & WsCharDspl(InxWsChar) & "}"
End If
RetnVal = Mid(RetnVal, 1, PosWsChar - 1) & InsStr & Mid(RetnVal, PosWsChar + NumWsChar)
Loop
Next
TidyTextForDspl = RetnVal
End Function
New section in response to question in comment
InStr
is not the most useful function for your requirement. I recommend Split
.
Split
splits a string on a delimiter and returns the parts as an zero-based, one-dimensioned array.
The documentation says Split
always returns a zero-based array and I have always found that to be true. However, there are functions that are affected by the Option Base
statement so I always use the LBound
function to be absolutely clear which element I am accessing.
This little macro uses Split
to split your example string. I have used Trim
to remove any leading or trailing spaces.
Option Explicit
Sub Test()
Dim Inx As Long
Dim Parts() As String
Parts = Split("S1 | ICM21449524 | XYZ Bank | P1 - Critical |Health Service Heartbeat Failure", "|")
For Inx = LBound(Parts) To UBound(Parts)
Debug.Print Inx & " [" & Trim(Parts(Inx)) & "]"
Next
End Sub
Second new section
You are not answering my question. Perhaps you do not understand its significance so I will give some demonstration code for the two most likely answers.
If you want a macro to process some emails, there are different ways of specifying which emails are to be processed.
One approach is for the user to select all the emails to be processed before starting the macro. If you click LeftMouse on an email, it is selected. If you then press and hold Shift while clicking Up or Down, you can select a block of contiguous emails. If you hold Ctrl while clicking LeftMouse on emails, you can select non-contiguous emails.
Select some emails and then run this macro:
Public Sub DemoExplorer()
Dim Exp As Outlook.Explorer
Dim ItemCrnt As MailItem
Dim NumSelected As Long
Set Exp = Outlook.Application.ActiveExplorer
NumSelected = Exp.Selection.Count
If NumSelected = 0 Then
Debug.Print "No emails selected"
Else
For Each ItemCrnt In Exp.Selection
With ItemCrnt
Debug.Print "--------------------------"
Debug.Print "From: " & .SenderName
Debug.Print "Subject: " & .Subject
Debug.Print "Received: " & Format(.ReceivedTime, "dMMMyy h:mm:ss")
End With
Next
End If
End Sub
The above macro is one of my standard demonstration macros. It outputs a number of properties of each of the selected emails to the immediate window. You are only interested in Subject but I decided to leave the others for reference.
Another approach is for the user to move the emails to be processed to a special folder with a name such as “ToProcess”. The macro is coded to look at folder “ToProcess” and to process the emails within it. After the emails have been processed, they can be moved on to another folder with a name such as “Processed”. This is not an approach I favour so I have no code to demonstrate it. Instead I explain how to amend the next macro to match this approach.
My most used approach is to search down Inbox for new emails with specific characteristics. The macro processes these emails and then moves them to a “Processed” folder. This approach saves the user the bother of searching for the emails to be processed and moving them twice.
The code below expects to find a folder “Processed2” within the default Inbox. Either create folder “Processed2” within the default Inbox and run my code unchanged or amend my code so FolderDest2
references a folder of your choice. This code processes any email with a pipe, “|”, in the Subject. You will need to expand my code so only the required emails are processed.
Public Sub DemoSearch()
Dim FolderDest2 As MAPIFolder
Dim FolderDest1 As MAPIFolder
Dim FolderSrc1 As MAPIFolder
Dim FolderSrc2 As MAPIFolder
Dim InxItemCrnt As Long
Dim InxPart As Long
Dim NS As Outlook.NameSpace
Dim SubjectPart() As String
Set NS = CreateObject("Outlook.Application").GetNamespace("MAPI")
' This is the easiest way to reference the default Inbox.
' However, you must be careful if, like me, you have multiple email addresses
' each with their own Inbox. The default Inbox may not be where you think it is.
Set FolderSrc1 = NS.GetDefaultFolder(olFolderInbox)
' This references the Inbox in a specific PST or OST file.
' "tonydallimore23@gmail.com" is the user name that Outlook gave the OST file in
' which it stores emails sent to this account when I created the account. The user
' name is the name Output displays to the user. The file name on disk is different.
Set FolderSrc2 = NS.Folders("tonydallimore23@gmail.com").Folders("Inbox")
' I do not know where you want to save processed emails. I have created
' FolderDest1 to show how to access a folder at the same level as Inbox
' but my code uses FolderDest2 which is a sub-folder of Inbox.
' This gets a reference to folder "Processed1" which is at the same level
' as the default Inbox.
' I have started at FolderSrc1 (Inbox) gone up one level to its parent
' (outlook data file) and doen to another child ("Processed1")
Set FolderDest1 = FolderSrc1.Parent.Folders("Processed1")
' This gets a reference to folder "Processed2" which is a sub-folder of
' the default Inbox.
Set FolderDest2 = FolderSrc1.Folders("Processed2")
' This examines the emails in reverse order.
' If I process email number 5 and then move it to another folder,
' the number of all subsequence emails is decreased by 1. If I looked at the
' emails in ascending sequence, email 6 would be ignored because it would have
' been renumbered wehn I looked for it. By looking at the emails in reverse
' sequence, I ensure email 6 has bee processed before the removal of email 5
' changes its number.
' I do not know how you identify the emails you want to process. I process
' any email with a pipe , "|", in the Subject
For InxItemCrnt = FolderSrc1.Items.Count To 1 Step -1
With FolderSrc1.Items.Item(InxItemCrnt)
If .Class = olMail Then
' I am only interested in mail items.
If .Subject <> "" Then
' ONlt attept split if there is a Subject
SubjectPart = Split(.Subject, "|")
If LBound(SubjectPart) <> UBound(SubjectPart) Then
' There is at least one pipe, "|", within the subject
Debug.Print "====="
Debug.Print " Sender " & .SenderEmailAddress
Debug.Print " Received " & Format(.ReceivedTime, "ddmmmyy hh:mm:ss")
Debug.Print " Subject: "
For InxPart = LBound(SubjectPart) To UBound(SubjectPart)
Debug.Print " " & Trim(SubjectPart(InxPart))
Next InxPart
.Move FolderDest2
End If ' LBound(SubjectPart) <> UBound(SubjectPart)
End If ' .Subject <> ""
End If ' .Class = olMail
End With ' FolderSrc1.Items.Item(InxItemCrnt)
Next InxItemCrnt
End Sub
If you prefer my second approach, you will need to amend the above code slightly. .Move FolderDest2
, near the bottom, must be deleted. The statement near the top to specify the source folder will require amendment. I recommend you retain the code to identify emails to be processed in case the case accidentally move an inappropriate email to the source folder.
I hope running these two macros will fully explain the significance of my question. I wanted to only provide the code for the email selection method you preferred. I have now provided the code for the two major approach. Select whichever best meets your requirements as the basis for your macro.