Besides programming, I am also a professional photographer. I recently set up an extremely successful photobooth... so successful I have about 500 photos, and a list of 60 emails (some pictures have multiple recipients)to send them to.
Email is the only way I can get the pictures to their respective owner, and I do not have time to manually send each photo to its owner in an email app, nor do I want to risk making mistakes in the process. All of the email addresses are in a text file, with the file locations of each image following the intended recipient. In addition to the pictures, I have one universal body text to send.
I have already looked into ASP, Macros, CDOSys, and some slightly confusing options with SMTP, but answers using these are more than welcome.
Any ideas on how to use the information in the text file to email each recipient with their photos?
tl;dr: I need to get 500 individual photos to 60 email addresses, without sending each picture manually, or giving someone someone else's photos. All of the information is organized in a text file.
Update: I have a few different versions of the text file. I have a text file straight out of a notepad editor, I have a csv file, and I have a version which delimits file paths with # and email addresses with tabs.
Using classic asp and web email server and assuming you can have created a csv file.
step 1. upload textFile.csv into server
with say emailAddress, pictureFileAddress etc.
step 2. import and emailer script (classic asp)
downloadFile = Server.MapPath("textFile.csv")
Set objFSO = CreateObject("Scripting.FileSystemObject")
if objFSO.FileExists(downloadFile) then
firstLine = true '... assume first line is header
Do Until objFile.AtEndOfLine OR finished
StrTemp = objFile.ReadLine
dataArray = Split(StrTemp, ",") '... assume just two fields for this e.g.
dataCount = UBound(dataArray)
email = dataArray(0)
picturefile = dataArray(1)
'... perform any data validation or Regexp
If email <> "" AND firstLine = false then
Set myMail=CreateObject("CDO.Message")
myMail.From = "yourfromemail"
myMail.ReplyTo = "yourreplyfromemail"
myMail.Subject = "Your picture"
'...create target file for attachment
fn1 = picturefile
fn2 = Server.MapPath(fn1)
myMail.AddAttachment fn2
myMail.HTMLBody = strMessage
myMail.Send
Set myMail = Nothing
end if
if firstLine then firstline = false
loop
End if
I hope this helps
Related
I have an MDB file which contains a number of tables and forms. Each field has a validation rule such as Is Null Or >=0 And <=255.
This access database is being converted into an online system using MySQL. Exporting all the data is easy using MDBTools (https://github.com/brianb/mdbtools).
However I can't find any way of exporting the validation rules. There are thousands of fields across over 100 tables so it's going to be important to export and import them rather than rewrite each one.
I don't really mind what format they're exported in, any sort of text format so I could do a regular expression or something will be fine.
However I haven't been able to find any information anywhere on exporting these validation rules.
Perhaps if it's not built into access by default then a VB script could be used to find the info and write it to a text file? I'm not really familiar with access or windows at all so if anyone could suggest if that was a possibility that would be great.
Using VBA allows you to retrieve field validation rules directly.
I realize it's probably too late to help you now. And, although it may not seem appropriate for someone unfamiliar with Access and VBA, this approach requires only a table, copying the code below into a standard module, and running it. So someone else may benefit.
I created my table, field_validation_rules, to store the text of the validation rule properties. The table includes 3 text fields: table_name; field_name; and validation_rule.
Public Sub GatherValidationRules()
Dim db As DAO.Database
Dim fld As DAO.Field
Dim rs As DAO.Recordset
Dim tdf As DAO.TableDef
Set db = CurrentDb
Set rs = db.OpenRecordset("field_validation_rules", dbOpenTable, dbAppendOnly)
For Each tdf In db.TableDefs
If Not (tdf.Name Like "~*" Or tdf.Name Like "MSys*") Then
For Each fld In tdf.Fields
If Len(fld.ValidationRule) > 0 Then
rs.AddNew
rs!table_name.Value = tdf.Name
rs!field_name.Value = fld.Name
rs!validation_rule.Value = fld.ValidationRule
rs.Update
End If
Next
End If
Next
rs.Close
End Sub
The ValidationRule property is a string value. If the property has not been assigned for a given field, ValidationRule is an empty string. The code skips those, storing only validation rules for fields which have them assigned.
If you want the collected validation rules in a text file, there a several options. I dumped mine to CSV like this:
DoCmd.TransferText acExportDelim, , "field_validation_rules", "C:\share\Access\field_validation_rules.txt", False
To anyone else finding this, this is how I wound up doing it. This was in Access 2003, it may be different in other versions.
First I went to Tools > Analyze > Documenter selected the table I wanted and used these settings:
I was then presented with what looked like a pdf or word doc (I don't think it is, but it doesn't really matter).
I then did File > Export and selected "Text Files .txt" and saved it to a location on my computer.
I then opened the .txt file in PHP (anywhere you can do regular expressions should be fine).
In my instance not every single field had validation rules and the validation rules did not appear if they were not set, which meant a regular expression to fetch the fieldID had more results than to fetch the validation rules.
So I used two regular expressions.
/SourceField:\s+(\S+).*?AllowZeroLength/msi
This gets everything betwenen SourceField and AllowZeroLength. AllowZeroLength is the first bit of repeating text after the validation rules.
I then used this regular expression to get the validation rules from within that string.
/ValidationRule:\s+(.*)\\r/
I had to use \r instead of new line, probably something to do with moving it from Windows to Ubuntu.
In PHP it looked like this:
<?php
$file_contents = file_get_contents('validations.txt');
$response = [];
preg_match_all('/SourceField:\s+(\S+).*?AllowZeroLength/msi', $file_contents, $matches);
for($i = 0; $i < count($matches[0]); $i++) {
$id = $matches[1][$i];
preg_match('/ValidationRule:\s+(.*)\\r/', $matches[0][$i], $validation_match);
$response[$id] = $validation_match[1] ?? null;
}
There is almost certainly a cleaner regular expression than this, but this was incredibly quick and I got exactly what I wanted.
I am writing an HTA file with VBScript as the scripting language. I have a function where the user is prompted to choose the folder in which they would like to save a document. I didn't write this code myself, but instead borrowed it from here.
Function SelectFolder(myStartFolder)
Dim objFolder, objItem, objShell
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.BrowseForFolder(0, "Select Folder to Save New File", 0, myStartFolder)
If IsObject(objFolder) Then SelectFolder = objFolder.Self.Path
End Function
I call this function in another one in order when I make the file and prompt the user to choose where to save it:
Sub Example()
Dim destPath, destFile, objWorkbook
destPath = SelectFolder(libPath)
destPath = destPath & "\Sample Export"
Set destFile = CreateObject("Excel.Application")
Set objWorkbook = destFile.Workbooks.Add()
objWorkbook.SaveAs(destPath)
(code to edit excel file)
End Sub
Example() works fine except when someone chooses to save their document in one of the four default libraries in Windows (Documents, Music, Pictures, Videos). In that case, I receive an error saying "The file could not be accessed" and indicating the error is at the line that says "objWorkbook.SaveAs(destPath)". The error box then gives me the following suggestions:
Make sure the specified folder exists
Make sure the folder that contains the file is not read-only
Make sure the file name does not contain any of the following characters: < > ? { } : | or *
Make sure the file/path name doesn't contain more than 218 characters.
The error occurs when I open the HTA file and click a button calling Example(), which then opens a dialog box to ask the user to choose the file location. When Documents, Music, Pictures, or Videos is chosen, a "Script Error" box pops up with the error message listed above. I am not familiar enough with VBScript to know what the problem is exactly. I would appreciate any suggestions as to what to do.
I don't know exactly what the solution to the above issue was. However, I noticed that the path I pass to SelectFolder had a typo in it. libPath was supposed to be to the %userprofile% from the environment variable. However, I had pluralized "userprofiles" so that it was %userprofiles% instead. This took me to somewhere that looked right but wasn't. I fixed the typo and now BrowseForFolder takes me to C:/Users/*username* like it's supposed to. It turns out that I was being sent to the Desktop location because of the fourth argument in BrowseForFolder, instead of the user profile like I wanted.
I have about 15 different slide decks, that contain 3-4 slides each. Each deck is comprised of "certificates" to be broken out and given to each individual recipient, who is named on the certificate. This process is repeated every month.
ideally, I would like to enable a VBA script to extract each sheet to save as (or print as) a PDF, and save the file with the name of the recipient named on the slide... is this possible?
The best I have found is this code, (which doesn't work on my mac, but works fine on a VM) which DOES separate the slides into PDF's, but I would like the naming to be changed.
Any help would be greatly appreciated!!
Sub ExportSlidesToIndividualPDF()
Dim oPPT As Presentation, oSlide As Slide
Dim sPath As String, sExt As String
Set oPPT = ActivePresentation
sPath = oPPT.FullName & "_Slide_"
sExt = ".pdf"
For Each oSlide In oPPT.Slides
i = oSlide.SlideNumber
oSlide.Select
oPPT.ExportAsFixedFormat _
Path:=sPath & i & sExt, _
FixedFormatType:=ppFixedFormatTypePDF, _
RangeType:=ppPrintSelection
Next
Set oPPT = Nothing
End Sub
Edit for further clarification:
I'm forced to run the script in my Windows Virtual Machine, and when I do that, I'm losing all of my formatting that I set up in my slides, created in office '11 (which is one of my big reasons to export to PDF in the first place).
A little more about my project:
1. I am compiling a couple thousand lines of "actions" (data), to determine a winner for a recognition award, based on criteria for 4 different award categories, for 12-15 different executives.
2. Results are tallied, then I retrieve the winners information (name, ID, and the same for their manager and executive) from an LDAP directory. Then put into a csv for mail-merge at later step.
3. A Template slide deck is used for all slides, (12-15 executives have 3-4 winners each).
4. Individual PDF certificates are created from those slides.
5. Congratulatory message is drafted, fields pulled from prepared csv for mail-merge, and then exported to outlook 2011 outbox (client offline).
6. I attach each individual certificate to each message manually in the outbox.
7. Send.
I have compiled sample set of the files linked here: Recognition Files (Sample)
On each slide there are one or several shapes. For the sake of illustration, assume that the recipient's name is in the first shape.
Sub ExportSlidesToIndividualPDF()
Dim oPPT As Presentation, oSlide As Slide
Dim sPath As String, sExt As String
Set oPPT = ActivePresentation
sExt = ".pdf"
For Each oSlide In oPPT.Slides
'## Retrieve the recipient's name from the shape and append it to the exported path:
sPath = oPPT.FullName & oSlide.Shapes(1).TextFrame.TextRange.Text
i = oSlide.SlideNumber
oSlide.Select
oPPT.ExportAsFixedFormat _
Path:=sPath & sExt, _
FixedFormatType:=ppFixedFormatTypePDF, _
RangeType:=ppPrintSelection
Next
Set oPPT = Nothing
End Sub
It may be more complicated, depending on how the slides are configured (e.g., if there is a shape that contains the name and other text, you will need a function to parse out the proper name and omit the rest, etc.
Provide more detail, about the problem if you need further assistance.
Sub GetALLEmailAddresses()
Dim objFolder As Folders
Set objFolder = Application.ActiveExplorer.Selection
Dim dic As New Dictionary
Dim strEmail As String
Dim strEmails As String
Dim objItem As MailItem
For Each objItem In objFolder.Items
strEmail = objItem.SenderEmailAddress
If Not dic.Exists(strEmail) Then
strEmails = strEmails + strEmail + ";"
dic.Add strEmail, ""
End If
Next
Debug.Print strEmails
End Sub
I use this code to get email address from message body. I'm not prefect in vb. is there any to help how to get email address from messages in outlook 2003?
In that case, I don't think there's anything built in, so I'd suggest that you don't bother with the SenderEmailAddress but instead just get out the Body and then search the text for email addresses. This will get somewhat complicated though since it might be difficult to be able to tell what's part of an email address and what isn't.
The easiest place to start with is to just look for any # in the text, and then search for the next whitespace on either side of the # and get everything between those whitespaces. But there are a lot of issues to think about. What if the user typed # for some other reason, or if the email contains something like The first email is xxx#test.com.The second email is xxx2#test.com (note the missing space between the . and the The), where your app might think that the email should be xxx#test.com.The.
Edited since my answer was based on a complete misunderstanding of the question.
Programmatically, of course.
Having already asked this question on superuser, I'm looking at writing a simple macro to pull down the displayed image in an HTML message (email or feed) in outlook 2007, and allow me to save it to disk.
Unfortunately, I havent been able to find where in the OL object model I can reference either linked images, or the html content itself. Finding attached files is easy, its the linked/displayed images that is my issue.
Any help? Of course, if you have a better non-programmatic answer, I'll be glad to see that - over on superuser, of course...
This is based on the MSDN docs. I don't have Outlook to test it.
Assuming you have an email message open, you can call GetInspector method on the MailItem instance that you have & use its HTMLEditor property to get handle to the DOM.
From here on, you can call regular methods such as document.Images to get handle to all the image elements. I don't know, how one can save it locally to a disk but I am sure, there must be some method to do it.
I had a second look at shahkalpeshs answer and came up with the following solution:
(Written in Outlook 2003)
Option Explicit
Private Sub getImages()
Dim xmlhttp_ As xmlhttp
Dim htmldoc As Object
Dim currentImage As Object
Dim currentResponse() As Byte
Dim startTime As Date
Dim maxTime As Long
Dim pathFolder As String
Dim pathFull As String
Dim nrFile As Integer
pathFolder = "C:\YourFolder\Images\" '"(small fix for stackoverflow syntaxhighlighter)
maxTime = 30 ' max time to load 1 File in seconds '
If Me.ActiveWindow.CurrentItem.GetInspector.EditorType = olEditorHTML Then
Set htmldoc = Me.ActiveWindow.CurrentItem.GetInspector.HTMLEditor
Set xmlhttp_ = New xmlhttp
For Each currentImage In htmldoc.images
xmlhttp_.Open "GET", currentImage.src
If Left(currentImage.src, 8) <> "BLOCKED:" Then
xmlhttp_.Send
startTime = Now
pathFull = pathFolder & currentImage.nameProp
pathFull = Replace(pathFull, "?", vbNullString)
pathFull = Replace(pathFull, "&", vbNullString)
Do While xmlhttp_.readyState <> 4
If DateTime.DateDiff("s", startTime, Now) > maxTime Then Exit Do
DoEvents
Loop
If xmlhttp_.readyState = 4 Then
If Dir(pathFull) <> "" Then Kill pathFull
nrFile = freeFile
Open pathFull For Binary As #nrFile
currentResponse = xmlhttp_.responseBody
Put #nrFile, , currentResponse
Close #nrFile
End If
End If
Next currentImage
End If
Set xmlhttp_ = Nothing
Set currentImage = Nothing
Set htmldoc = Nothing
End Sub
This code will download all the images that are displayed in your ActiveWindow and save them in a folder.
You will need to add a Reference to Microsoft XML (any version >= 2.6 should work) through Tools->References in the VBA Editor
If you want to, you can also set a Reference to the Microsoft HTML Object Library and change:
Dim htmldoc As Object
Dim currentImage As Object
to:
Dim htmldoc As HTMLDocument
Dim currentImage As HTMLImg
Regarding your comment:
#marg, Thanks for the detailed response. I still cant believe the solution has to be so convoluted - the image is already displaying, why should I have to download it again? And what if I want to save only a single image? (In Outlook 2003, you were able to right click on the image and select save as... now no more.) Since this is the closes to an actual workable solution, and since there doesnt seem to be any better solution in current Outlook - i'm giving you the bounty...
I don't have 2007 to look for a non-programming solution.
I do not believe that the MailItem Object (CurrentItemin my solution is a MailItem) differs much between the versions (but I base that assumption on 0 % research :D) and I was not able to locate the direct local path where the displayed images are stored even though I am pretty sure they should be in your browsers cache-folder. Crawling your folder for a file with the name currentImage.nameProp and copying it to your destination folder would be an alternative solution. Simply redownloading the image should not be that bad :D