I learning how to use Microsoft Word wildcards and codes to help me in my position as a medical editor. A big part of my job is submitting manuscripts to medical journals for review, and each journal has very specific requirements.
Most of the journals we submit manuscripts to require that medical terms/phrases be abbreviated only if they are used three or more times. For example, the term “Overall Survival” can be abbreviated to OS if the term is referenced at least three times in the text. If the text only mentions “Overall Survival” once or twice, it is preferred that the term remain expanded, and it should not be abbreviated to OS.
We have been using the PerfectIt system, by Intelligent Editing. This Word widget scans for abbreviations that are only used once and will flag them for our review, but does not pick up if an abbreviation is only used twice in the selected text. We are hoping to find some solution (my thought would be some sort of wildcard search or macro) that will be able to detect if an abbreviation is used only one or two times.
I saw this similar post on stackoverflow, but it seemed to do with code. I will need this to be on a company computer that I do not have administrative access to, and furthermore, I know nothing about code. I appreciate any help, guidance, or directions for further research!
Thank you!
Edit: I could use a wildcard search to make all of the two+ capitalized letters highlighted by using <[A-Z]{2,}>, then formatting them as highlighted, if this would help with any macros.
For any given abbreviation, you could use a macro like:
Sub Demo()
Application.ScreenUpdating = False
Dim i As Long
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = InputBox("What is the Text to Find")
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = True
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
End With
Do While .Find.Found
i = i + 1
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
MsgBox i & " instances found."
End Sub
For PC macro installation & usage instructions, see: http://www.gmayor.com/installing_macro.htm
For Mac macro installation & usage instructions, see: https://wordmvp.com/Mac/InstallMacro.html
Provided there's at least one occurrence of the abbreviation in parens you could use a macro like the following. The macro checks the contents of a document for upper-case/numeric parenthetic abbreviations it then looks backwards to try to determine what term they abbreviate. For example:
World Wide Web (WWW)
Naturally, given the range of acronyms in use, it’s not foolproof and, if a match isn’t made, the preceding sentence (in VBA terms) is captured so the user can edit the output. A table is then built at the end of the document, which is then searched for all references to the acronym (other than for the definition) and the counts and page numbers added to the table.
Note that the macro won't tell you how many times 'World Wide Web' appears in the document, though. After all, given your criteria, it's impossible to know what terms should have been reduced to an acronym but weren't.
Sub AcronymLister()
Application.ScreenUpdating = False
Dim StrTmp As String, StrAcronyms As String, i As Long, j As Long, k As Long, Rng As Range, Tbl As Table
StrAcronyms = "Acronym" & vbTab & "Term" & vbTab & "Page" & vbTab & "Cross-Reference Count" & vbTab & "Cross-Reference Pages" & vbCr
With ActiveDocument
With .Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWildcards = True
.Wrap = wdFindStop
.Text = "\([A-Z0-9]{2,}\)"
.Replacement.Text = ""
.Execute
End With
Do While .Find.Found = True
StrTmp = Replace(Replace(.Text, "(", ""), ")", "")
If (InStr(1, StrAcronyms, .Text, vbBinaryCompare) = 0) And (Not IsNumeric(StrTmp)) Then
If .Words.First.Previous.Previous.Words(1).Characters.First = Right(StrTmp, 1) Then
For i = Len(StrTmp) To 1 Step -1
.MoveStartUntil Mid(StrTmp, i, 1), wdBackward
.Start = .Start - 1
If InStr(.Text, vbCr) > 0 Then
.MoveStartUntil vbCr, wdForward
.Start = .Start + 1
End If
If .Sentences.Count > 1 Then .Start = .Sentences.Last.Start
If .Characters.Last.Information(wdWithInTable) = False Then
If .Characters.First.Information(wdWithInTable) = True Then
.Start = .Cells(.Cells.Count).Range.End + 1
End If
ElseIf .Cells.Count > 1 Then
.Start = .Cells(.Cells.Count).Range.Start
End If
Next
End If
StrTmp = Replace(Replace(Replace(.Text, " (", "("), "(", "|"), ")", "")
StrAcronyms = StrAcronyms & Split(StrTmp, "|")(1) & vbTab & Split(StrTmp, "|")(0) & vbTab & .Information(wdActiveEndAdjustedPageNumber) & vbTab & vbTab & vbCr
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
StrAcronyms = Replace(Replace(Replace(StrAcronyms, " (", "("), "(", vbTab), ")", "")
Set Rng = .Characters.Last
With Rng
If .Characters.First.Previous <> vbCr Then .InsertAfter vbCr
.InsertAfter Chr(12)
.Collapse wdCollapseEnd
.Style = "Normal"
.Text = StrAcronyms
Set Tbl = .ConvertToTable(Separator:=vbTab, NumRows:=.Paragraphs.Count, NumColumns:=5)
With Tbl
.Columns.AutoFit
.Rows(1).HeadingFormat = True
.Rows(1).Range.Style = "Strong"
.Rows.Alignment = wdAlignRowCenter
End With
.Collapse wdCollapseStart
End With
End With
Rng.Start = ActiveDocument.Range.Start
For i = 2 To Tbl.Rows.Count
StrTmp = "": j = 0: k = 0
With .Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Format = False
.Forward = True
.Text = "[!\(]" & Split(Tbl.Cell(i, 1).Range.Text, vbCr)(0) & "[!\)]"
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
If Not .InRange(Rng) Then Exit Do
j = j + 1
If k <> .Duplicate.Information(wdActiveEndAdjustedPageNumber) Then
k = .Duplicate.Information(wdActiveEndAdjustedPageNumber)
StrTmp = StrTmp & k & " "
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Tbl.Cell(i, 4).Range.Text = j
StrTmp = Replace(Trim(StrTmp), " ", ",")
If StrTmp <> "" Then
'Add the current record to the output list (StrOut)
StrTmp = Replace(Replace(ParseNumSeq(StrTmp, "&"), ",", ", "), " ", " ")
End If
Tbl.Cell(i, 5).Range.Text = StrTmp
Next
End With
Set Rng = Nothing: Set Tbl = Nothing
Application.ScreenUpdating = True
End Sub
Function ParseNumSeq(StrNums As String, Optional StrEnd As String)
'This function converts multiple sequences of 3 or more consecutive numbers in a
' list to a string consisting of the first & last numbers separated by a hyphen.
' The separator for the last sequence can be set via the StrEnd variable.
Dim ArrTmp(), i As Long, j As Long, k As Long
ReDim ArrTmp(UBound(Split(StrNums, ",")))
For i = 0 To UBound(Split(StrNums, ","))
ArrTmp(i) = Split(StrNums, ",")(i)
Next
For i = 0 To UBound(ArrTmp) - 1
If IsNumeric(ArrTmp(i)) Then
k = 2
For j = i + 2 To UBound(ArrTmp)
If CInt(ArrTmp(i) + k) <> CInt(ArrTmp(j)) Then Exit For
ArrTmp(j - 1) = ""
k = k + 1
Next
i = j - 2
End If
Next
StrNums = Join(ArrTmp, ",")
StrNums = Replace(Replace(Replace(StrNums, ",,", " "), ", ", " "), " ,", " ")
While InStr(StrNums, " ")
StrNums = Replace(StrNums, " ", " ")
Wend
StrNums = Replace(Replace(StrNums, " ", "-"), ",", ", ")
If StrEnd <> "" Then
i = InStrRev(StrNums, ",")
If i > 0 Then
StrNums = Left(StrNums, i - 1) & Replace(StrNums, ",", " " & Trim(StrEnd), i)
End If
End If
ParseNumSeq = StrNums
End Function
Basically what I am trying to do is, sending an email for every used row on the target worksheet, each row has the details of the addresses, subject line, table with values etc.
So I can't seem to get it working, as it only dispatches one email from the first target row (2nd row).
I have tried using a combination of For Each and For i = 1 to LR which aren't working. I suspect it is to do with the cell references.
Here is the code:
Sub TestEmail1()
Application.ScreenUpdating = False
Dim aOutlook As Object
Dim aEmail As Object
Dim rngeAddresses As Range, rngeCell As Range, strRecipients As String
Dim ccAddresses As Range, ccCell As Range, ccRecipients As String
Dim rngeSubject As Range, SubjectCell As Range, SubjectContent As Variant
Dim rngeBody As Range, bodyCell As Range, bodyContent As Variant
Dim Table1 As Range
Dim i As Integer
For Each c In ActiveSheet.UsedRange.Columns("A").Cells
Set rng = ActiveSheet.UsedRange
LRow = rng.Rows.Count
For i = 2 To LRow
Set Table1 = Worksheets(1).Range("K1:R1")
Set Table2 = Worksheets(2).Range("K" & i & ":" & "R" & i)
Set aOutlook = CreateObject("Outlook.Application")
Set aEmail = aOutlook.CreateItem(0)
'set sheet to find address for e-mails as I have several people to
'mail to
Set rngeAddresses = ActiveSheet.Range("B" & i)
For Each rngeCell In rngeAddresses.Cells
strRecipients = strRecipients & ";" & rngeCell.Value
Next
Set ccAddresses = ActiveSheet.Range("C" & i)
For Each ccCell In ccAddresses.Cells
ccRecipients = ccRecipients & ";" & ccCell.Value
Next
Set rngeSubject = ActiveSheet.Range("D" & i)
For Each SubjectCell In rngeSubject.Cells
SubjectContent = SubjectContent & SubjectCell.Value
Next
Set rngeBody = ActiveSheet.Range("E" & i)
For Each bodyCell In rngeBody.Cells
bodyContent = bodyContent & bodyCell.Value
Next
'set Importance
'aEmail.Importance = 2
'Set Subject
aEmail.Subject = rngeSubject
'Set Body for mail
'aEmail.Body = bodyContent
aEmail.HTMLBody = bodyContent & "<br><br><br>" & RangetoHTML_ (Table1)
aEmail.To = strRecipients
aEmail.CC = ccRecipients
aEmail.Send
Exit Sub
Next i
Next c
End Sub
There is an Exit Sub at the end of your inner loop that makes the code exit from the procedure after the first iteration:
Sub TestEmail1()
...
For Each c In ActiveSheet.UsedRange.Columns("A").Cells
...
For i = 2 To LRow
...
Exit Sub
Next i
Next c
End Sub
Remove it and processing should continue as desired.
This macro works on line 5 ,so i need this macro to work on all lines in one sheet instead of one macro for each line. Row X and email range A:L are copy paste in all lines i.e.( X1 A1:L1 | X2 ,A2:L2 ...)
Dim X5 As Variant
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("X5").Value = 1 And X5 <> 1 Then
ActiveSheet.Range("A5:L5").Select
ActiveWorkbook.EnvelopeVisible = True
With ActiveSheet.MailEnvelope
.Introduction = " send thru macro "
.Item.To = "email#gmail.com"
.Item.Subject = "ALERT"
.Item.Send
End With
End If
X5 = Range("X5").Value
End Sub
Not sure if you got your answer or not so I am attempting to answer this question.
To make it flexible for any row, you can store the row of the current cell in a variable using Target.Row and then simply use that to construct your range.
Also to understand how Worksheet_Change works, you may want to see THIS
Is this what you are trying?
Dim X5 As Variant
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
'~~> Check if the chnage happened to multiple cells
If Target.cell.CountLarge > 1 Then Exit Sub
Dim Rw As Long
'~~> Get the row number of the cell that was changed
Rw = Target.Row
If Range("X" & Rw).Value = 1 And X5 <> 1 Then
Application.EnableEvents = False
Range("A" & Rw & ":L" & Rw).Select
ActiveWorkbook.EnvelopeVisible = True
With ActiveSheet.MailEnvelope
.Introduction = " send thru macro "
.Item.To = "email#gmail.com"
.Item.Subject = "ALERT"
.Item.Send
End With
End If
X5 = Range("X" & Rw).Value
Letscontinue:
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
I searched but couldn't find what I'm looking for.
How do I convert a normal Date() in ASP Classic to a string in the format dd-monthname-YYYY?
Here is an example:
Old date (mm/dd/YYYY) : 5/7/2013
New date (dd-monthname-YYYY) : 7-May-2013
Dim Dt
Dt = CDate("5/7/2013")
Response.Write Day(Dt) & "-" & MonthName(Month(Dt)) & "-" & Year(Dt)
' yields 7-May-2013
' or if you actually want dd-monthname-YYYY instead of d-monthname-YYYY
Function PadLeft(Value, Digits)
PadLeft = CStr(Value)
If Len(PadLeft) < Digits Then
PadLeft = Right(String(Digits, "0") & PadLeft, Digits)
End If
End Function
Response.Write PadLeft(Day(Dt), 2) & "-" & MonthName(Month(Dt)) & "-" & Year(Dt)
'yields 07-May-2013
I wrote an ASP Classic date handling object a while back that might be of use to you. It has a .Format() method that lets you pass in format specifiers just like the Format() function from VB/VBA. If there are any parts missing, I apologize--but this should be a giant leap forward toward natural date formatting.
Private pMillisecondMatch
Function RemoveMillisecondsFromDateString(DateString) ' Handle string dates from SQL Server that have milliseconds attached
If IsEmpty(pMillisecondMatch) Then
Set pMillisecondMatch = New RegExp
pMillisecondMatch.Pattern = "\.\d\d\d$"
pMillisecondMatch.Global = False
End If
RemoveMillisecondsFromDateString = pMillisecondMatch.Replace(DateString, "")
End Function
Function DateConvert(DateValue, ValueIfError)
On Error Resume Next
If IsDate(DateValue) Then
DateConvert = CDate(DateValue)
Exit Function
ElseIf TypeName(DateValue) = "String" Then
DateValue = RemoveMillisecondsFromDateString(DateValue)
If IsDate(DateValue) Then
DateConvert = CDate(DateValue)
Exit Function
End If
End If
DateConvert = ValueIfError
End Function
Class AspDate
Private pValue
Public Default Property Get Value()
Value = pValue
End Property
Public Property Set Value(DateValue)
If TypeName(DateValue) = "AspDate" Then
pValue = DateValue.Value
Else
Err.Raise 60020, "Class AspDate: Invalid object type " & TypeName(DateValue) & " passed to Value property."
End If
End Property
Public Property Let Value(DateValue)
pValue = DateConvert(DateValue, Empty)
End Property
Public Property Get FormattedDate()
FormattedDate = Format("yyyy-mm-dd hh:nn:ss")
End Property
Public Function Format(Specifier)
Dim Char, Code, Pos, MonthFlag
Format = "": Code = ""
If IsEmpty(Value) Then
Format = "(Empty)"
End If
Pos = 0
MonthFlag = False
For Pos = 1 To Len(Specifier) + 1
Char = Mid(Specifier, Pos, 1)
If Char = Left(Code, 1) Or Code = "" Then
Code = Code & Char
Else
Format = Format & Part(Code, MonthFlag)
Code = Char
End If
Next
End Function
Private Function Part(Interval, MonthFlag)
Select Case LCase(Left(Interval, 1))
Case "y"
Select Case Len(Interval)
Case 1, 2
Part = Right(CStr(Year(Value)), 2)
Case 3, 4
Part = Right(CStr(Year(Value)), 4)
Case Else
Part = Right(CStr(Year(Value)), 4)
End Select
Case "m"
If Not MonthFlag Then ' this is a month calculation
MonthFlag = True
Select Case Len(Interval)
Case 1
Part = CStr(Month(Value))
Case 2
Part = Right("0" & CStr(Month(Value)), 2)
Case 3
Part = MonthName(Month(Value), True)
Case 4
Part = MonthName(Month(Value))
Case Else
Part = MonthName(Month(Value))
End Select
Else ' otherwise it's a minute calculation
Part = Right("0" & Minute(Value), 2)
End If
Case "n"
Part = Right("0" & Minute(Value), 2)
Case "d"
Part = CStr(Day(Value))
If Len(Part) < Len(Interval) Then
Part = Right("0" & Part, Len(Interval))
End If
Case "h"
MonthFlag = True
Part = CStr(Hour(Value))
If Len(Part) < Len(Interval) Then
Part = Right("0" & Part, Len(Interval))
End If
Case "s"
Part = Right("0" & Second(Value), 2)
Case Else ' The item is not a recognized date interval, just return the value
Part = Interval
End Select
End Function
End Class
Function NewDate(Value)
Set NewDate = New AspDate
NewDate.Value = Value
End Function
Function NewDateWithDefault(Value, DefaultValue)
Set NewDateWithDefault = New AspDate
If Value = Empty Then
NewDateWithDefault.Value = DefaultValue
Else
NewDateWithDefault.Value = Value
End If
End Function
Here's example code using the above class:
<%=NewDate(Checkin.Parameters.Item("#DOB").Value).Format("mm/dd/yyyy")%>
To get the format you've noted above, you would do:
.Format("d-mmmm-yyyy")
Has anyone been able to download email that contains attachment with CDO in vb6?
Can you help me with an example?
I'm still not sure where you want to retrieve email from but here is some code for retrieving email from an Exchange server. I did this as an experiment to learn some methods I would need on another project so it is not production quality but should get you started. This code is dependent on an Exchange client already being setup on the computer this is running on.
This function creates a session and logs in:
Function Util_CreateSessionAndLogon(Optional LogOnName As Variant) As Boolean
On Error GoTo err_CreateSessionAndLogon
Set objSession = CreateObject("MAPI.Session")
objSession.Logon , , False, False
Util_CreateSessionAndLogon = True
Exit Function
err_CreateSessionAndLogon:
Util_CreateSessionAndLogon = False
Exit Function
End Function
This function get information on items in the inbox and demonstrates some of the available properties.
Public Function GetMessageInfo(ByRef msgArray() As String) As Long
Dim objInboxFolder As Folder ' Folder object
Dim objInMessages As mapi.Messages ' Messages collection
Dim objMessage As Message ' Message object
Dim InfoRtnString
Dim i As Long
Dim lngMsgCount As Long
InfoRtnString = ""
If objSession Is Nothing Then
If Util_CreateSessionAndLogon = False Then
Err.Raise 429, "IBS_MAPI_CLASS", "Unable to create MAPI session object."
Exit Function
End If
End If
Set objInboxFolder = objSession.Inbox
Set objInMessages = objInboxFolder.Messages
lngMsgCount = objInMessages.Count
ReDim msgArray(0) 'initalize the array
For Each objMessage In objInMessages
If i / lngMsgCount * 100 > 100 Then
RaiseEvent PercentDone(100)
Else
RaiseEvent PercentDone(i / lngMsgCount * 100)
End If
InfoRtnString = ""
i = i + 1
ReDim Preserve msgArray(i)
InfoRtnString = InfoRtnString & Chr$(0) & objMessage.ID
InfoRtnString = InfoRtnString & Chr$(0) & objMessage.Subject
InfoRtnString = InfoRtnString & Chr$(0) & objMessage.Sender
InfoRtnString = InfoRtnString & Chr$(0) & objMessage.TimeSent
InfoRtnString = InfoRtnString & Chr$(0) & objMessage.TimeReceived
InfoRtnString = InfoRtnString & Chr$(0) & "" 'objMessage.Text
InfoRtnString = InfoRtnString & Chr$(0) & objMessage.Unread
InfoRtnString = InfoRtnString & Chr$(0) & objMessage.Attachments.Count
msgArray(i) = InfoRtnString
DoEvents
Next
GetMessageInfo = i
End Function
This function demonstrates getting attachments from a message.
Function GetAttachments(msgID As String, lstBox As ListBox) As Boolean
Dim objMessage As Message ' Messages object
Dim AttchName As String
Dim i As Integer
Dim x As Long
If objSession Is Nothing Then
x = Util_CreateSessionAndLogon()
End If
Set objMessage = objSession.GetMessage(msgID)
For i = 1 To objMessage.Attachments.Count
Select Case objMessage.Attachments.Item(i).Type
Case Is = 1 'contents of a file
AttchName = objMessage.Attachments.Item(i).Name
If Trim$(AttchName) = "" Then
lstBox.AddItem "Could not read"
Else
lstBox.AddItem AttchName
End If
lstBox.ItemData(lstBox.NewIndex) = i
Case Is = 2 'link to a file
lstBox.AddItem objMessage.Attachments.Item(i).Name
lstBox.ItemData(lstBox.NewIndex) = i
Case Is = 1 'OLE object
Case Is = 4 'embedded object
lstBox.AddItem "Embedded Object"
lstBox.ItemData(lstBox.NewIndex) = i
End Select
Next i
GetAttachments = True
End Function