I need to enter around 3 pieces of data into a website I don't own, press submit, and scrape a few pieces of data. I need to repeat this using different dates around 50 times. I've done this before for stuff I've reused a lot with Powershell. However, I was wondering if there was something simple like point and click I could use as if I spend hours on this I could have just as easily typed in the data and copied the results into a spreadsheet.
Any browser will do.
You can try to use IE automation using VBA to scrape the data from IE and paste it in to Excel Workbook.
Example:
Sub Automate_IE_Load_Page()
'This will load a webpage in IE
Dim i As Long
Dim URL As String
Dim IE As Object
Dim objElement As Object
Dim objCollection As Object
'Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")
'Set IE.Visible = True to make IE visible, or False for IE to run in the background
IE.Visible = True
'Define URL
URL = "https://www.example.com"
'Navigate to URL
IE.Navigate URL
' Statusbar let's user know website is loading
Application.StatusBar = URL & " is loading. Please wait..."
' Wait while IE loading...
'IE ReadyState = 4 signifies the webpage has loaded (the first loop is set to avoid inadvertently skipping over the second loop)
Do While IE.ReadyState = 4: DoEvents: Loop 'Do While
Do Until IE.ReadyState = 4: DoEvents: Loop 'Do Until
'Webpage Loaded
Application.StatusBar = URL & " Loaded"
'Unload IE
Set IE = Nothing
Set objElement = Nothing
Set objCollection = Nothing
End Sub
References:
(1) Automate Internet Explorer (IE) Using VBA
(2) VBA Web Scraping with GetElementsByTagName
(3) IE (Internet Explorer) Automation using Excel VBA
Further, You can try to modify the code based on your requirement.
Related
I have built a form that stores certain contact data on it. I want to include a couple of buttons/functions to keep the user in the form as much as possible versus switching between Outlook components (calendar, mail, etc.).
In this case the user can swap email addresses from separate ListBoxes and when they hit the button it will use the emails within one of them. Using VBS because I'm dealing with custom Outlook forms.
Sub GenerateButton_Click()
'Generates Email with all of the CCs
'Variables
Set FormPage = Item.GetInspector.ModifiedFormPages("Commands")
Set DoSend = FormPage.Controls("DoSendListBox")
mailList = ""
'Generate Email List
For x = 0 to (DoSend.ListCount - 1)
mailList = mailList & DoSend.List(x) & ";"
Next
'Compose Email
Set msg = Application.CreateItem(olMailItem)
msg.Subject = "Hello World!"
msg.To = mailList
End Sub
What Happens
- it compiles
- nothing happens on click
Research
- online forums usually in VBA
- relevant articles use outside connection rather than from within outlook
SOLVED
Note: Click on the "script" option and select the object item. From the new window you can navigate through the classes and from this I was able to find MailItem. You can see all of the methods/properties on the right hand pane.
It Turns out the correct syntax was:
Set msg = Application.CreateItem(MailItem)
msg.Display
At the moment I have a project with about 20 forms and sometimes I want to make small adjustments to them. So I created a piece of code to delete the forms and then recreate them the way I want.
The problem is that one line of code keeps giving me Path/File access error (Error 75).
This is a small piece of the code:
Sub makeForm(formName As String)
Dim form As Object
'These lines delete the old form
Set form = ThisWorkbook.VBProject.VBComponents(formName)
ThisWorkbook.VBProject.VBComponents.Remove VBComponent:=form
'This line creates the new form
Set form = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)
'These lines give the new form a few properties
With form
.Properties("Name") = formName 'This is the line of code that gives the error
.Properties("Caption") = formName
.Properties("Width") = 320
.Properties("Height") = 242
End With
End Sub
Can someone please tell me how I can make sure this error no longer appears? By the way, this error also appears when I manually want to change the name of a form after this macro failed, but doesn't when I do it before the macro failed.
PS: I'm new to this site so sorry if I made any rookie mistakes.
Saving the workbook after you've removed the userform seems to clear the error.
'These lines delete the old form
Set form = ThisWorkbook.VBProject.VBComponents(formName)
ThisWorkbook.VBProject.VBComponents.Remove VBComponent:=form
Set form = Nothing
ThisWorkbook.Save
I guess Excel refreshes some internal values when it saves.
I have code to parse emails and add "tel:" links to phone numbers, but the modified email body doesn't get shown in the Outlook Reading Pane until the user manually reloads it (view another email, come back to this one).
I've tried a few hacks like Inspector.Display, and ActiveExplorer.ClearSelection ActiveExplorer.AddToSelection, but I can't get consistent results (Display will open new Inspectors for some users, very undesirable).
I was also going to investigate hooking the event sooner. Somehow accessing the email body before Outlook renders it, to avoid the need to refresh. I'm very new to VSTO, so I don't know what event would have access to the MailItem but happen after a user selects it and before it is rendered. I have thought about only processing new mail, but that doesn't help when I roll out this addin, only going forward.
Here is my current ItemLoad sub:
Private Sub Application_ItemLoad(Item As Object)
Dim myObj As Outlook.MailItem
Dim ob As Object
ob = GetCurrentItem()
If TypeOf ob Is Outlook.MailItem Then
myObj = ob
Dim oldbody As String = myObj.Body
If myObj.HTMLBody.Length > 0 Then
myObj.HTMLBody = RegularExpressions.Regex.Replace(myObj.HTMLBody, "(?<!tel:)(?<![2-9\.])(?<!\>\ )[+]?(1-)?(1)?[\(]?(?<p1>\d{3})[\)]?[\.\- ]?(?<p2>\d{3})[\.\- ]?(?<p3>\d{4})(?=[^\d])", " ${p1}-${p2}-${p3}")
Else
myObj.Body = RegularExpressions.Regex.Replace(myObj.Body, "(?<!tel:)(?<![2-9\.])[+]?(1-)?(1)?[\(]?(?<p1>\d{3})[\)]?[\.\- ]?(?<p2>\d{3})[\.\- ]?(?<p3>\d{4})(?=[^\d])", "tel:${p1}.${p2}.${p3}")
End If
myObj.Save()
refreshCurrentMessage()
End If
End Sub
GetCurrentItem() just returns either objApp.ActiveExplorer.Selection.Item(1) or objApp.ActiveInspector.CurrentItem based on TypeName(objApp.ActiveWindow)
Outlook doesn't reflect changes made through the OOM immediately. You need to switch to another folder/email to get the item refreshed because there is no way to update the item on the fly.
You can use the CurrentFolder property of the Explorer class which allows to set a Folder object that represents the current folder displayed in the explorer. Thus, the view will be switched to another folder. Then you can set the CurrentFolder folder to initial folder.
Also I'd suggest releasing all underlying COM objects instantly. Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object.
I am trying to make a vb script to log into my facebook and update my status. The problem is, the submit button does not have an ID I can find using the page info with Chrome. The script I have so far is:
Try
Dim fileReader As String
fileReader = My.Computer.FileSystem.ReadAllText("pathtotext") ' I sensoored my path
fileReader2 = My.Computer.FileSystem.ReadAllText("pathtotext") 'I sensored my path
WebBrowser1.Document.GetElementById("email").SetAttribute("value", fileReader2)
WebBrowser1.Document.GetElementById("pass").SetAttribute("value", fileReader)
WebBrowser1.Document.GetElementById("loginbutton").InvokeMember("click")
Catch ex As Exception
WebBrowser1.Document.GetElementById("u_0_10").SetAttribute("value", "Can I make a status?")
WebBrowser1.Document.GetElementById("submit").InvokeMember("click")
End Try
All of this works, except the submit button. I used "submit" because that was the type and no ID is showing up. Thanks in advance for all help.
P.S - For future reference, how did you find the id for this button? "If you give a starving man a fish he shall be filled; teach him to fish, however and he shall never go hungry again" - Anonymous
you can use this
Dim htmlElements As HtmlElementCollection = WebBrowser1.Document.All
For Each ClickOnElementButton As HtmlElement In htmlElements
If ClickOnElementButton.InnerText = "Post" Then
ClickOnElementButton.InvokeMember("click")
End If
Next
instead of the old code
Is there a way to add an attachment to an email you're sending out without the attachment being on the filesystem? From reading over the DOM (http://msdn.microsoft.com/en-us/library/bb175153%28office.12%29.aspx) it says that the attachment source can be either a file path or "an Outlook item that constitutes the attachment". I don't use VBA of the office DOMs all that much and I'm not sure what this is. In addition, all the examples I can find are only giving usage examples by using the filesystem path.
I'm calling this from Word for documents that create themselves by filling out some form fields, then print themselves. I'd like them to go out via E-mail as well, but have no need for a permanent copy of the created file. I do realize that I could save them off to a temp directory, attach the saved file, then delete the file once the mail object is sent. It seems a waste to do this though.
Is there an way I can have Word pass the in-memory Document object off to Outlook to attach to the email?
The answer is no, you cannot attach an in-memory document to an outlook mailitem without saving it to disk first.
Oesor,
I made an assumption that email should get sent automatically, so SendMail method is out.
I tried a couple of things to see whether it would work. In both cases code would be embedded in your Word file.
In pre-2007 Word you could use RoutingSlip functionality:
ActiveDocument.HasRoutingSlip = True 'Creates RoutingSlip
With ActiveDocument.RoutingSlip
.Subject = "email Subject"
.AddRecipient = "recipient#domain.com"
.Delivery = wdAllAtOnce
End With
ActiveDocument.Route
Apparently, this code doesn't work in Word 2007. So instead you can use SendForReview functionality:
ActiveDocument.SendForReview "recipient#domain.com", "email subject", False, True
Email gets sent right away (w/o the popup Outlook window), but a couple of caveats exist: the document has to have a corresponding file - it won't work for a new document that has never been saved, and the first time the recipient opens the attached document from e-mail there may be a popup message about starting the review process.
I hope this helps,
Max.
This should work for you, if the relevant attachment source is an inline item, such as an embedded image. I have not tried it with attached files that are not inline but it may work there too. The basic ideas are:
1) Treat the content of the Emails as a Word document because the native Editor for Outlook is Word.
2) Use Word's Copy and Paste to carry everything around with you via the Clipboard because it is a well tested approach. In the example, I have pasted the new section in at the start in a new Paragraph but you could obviously place it anywhere you want.
The strange thing is, though, (see the Debug.Print) that the Attachments Count in the To document does not change, even though the inline images are all where they should be and can be seen and Sent. Have Outlook fun! (The .olm files in the example are simply Outlook.MailItems that have been saved as Template files. They could just as easily be MailItems from an Outlook folder.)
Private Sub TestAttach()
'Places inline Attachment information into a different MailItem
Dim OlTo As Outlook.MailItem
Dim OlFrom As Outlook.MailItem
Dim DocTo As Word.Document
Dim DocFrom As Word.Document
Dim R As Word.Range
Dim R1 As Word.Range
Dim R2 As Word.Range
Dim lStart As Long
Dim lEnd As Long
Set OlFrom = Outlook.CreateItemFromTemplate("C:\Temp\OlTemplateWithSomeOtherAttachments.oft")
Set OlTo = Outlook.CreateItemFromTemplate("C:\Temp\OlTemplateWithSomeAttachments.oft")
Debug.Print "From file starts with " & OlFrom.Attachments.Count & " attachments."
Debug.Print "To file starts with " & OlTo.Attachments.Count & " attachments."
Set DocFrom = OlFrom.GetInspector.WordEditor
Set DocTo = OlTo.GetInspector.WordEditor
OlFrom.Display
OlTo.Display
Set R2 = DocFrom.Content
With R2.Find 'Note: Find settings are 'sticky' and do not need to be repeated on the next find.
.Forward = True
.Wrap = wdFindStop 'Do not loop back to the start of the document
.Format = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Text = "Start flag for Section with Attachments" 'Find the start of the section to move
.Execute
lStart = R2.Start
.Text = "End flag for Section with Attachments" 'Find the end of the section to move
R2.Collapse wdCollapseEnd
.Execute
lEnd = R2.Start
End With
'OlFrom.Display
Set R2 = DocFrom.Range(lStart, lEnd)
'R2.Select
R2.Copy
Set R = DocTo.Range(1, 1)
R.InsertParagraphBefore
'Place the new inline attachments in the To MailItem
Set R = DocTo.Range(1, 1)
R.Paste
OlTo.Display
Debug.Print OlTo.Attachments.Count; "To file ends with " & OlTo.Attachments.Count & " attachments, the same as the original number but all the inline images show."
End Sub