VBA Excel - Insert Picture with Url - Credentials Window - excel

I have a macro set up to navigate through a website and scrape data + images to create a product comparison list. The small issue i'm having is that when trying to insert a picture using VBA i sometimes get a windows security prompt window to insert login details. If i cancel the window, the code works correctly but having this pop-up every product in a range of 50 items isn't ideal.
I've found a few image url's that seem to insert without this pop-up showing, which suggests to me that it's to do with how secure microsoft see's the website.
I've also tried both .Pictures.Insert and .Shapes.AddPicture. Both have the same issue
The code below using the first link will show the login window, but if you use the second link it will work without a pop-up
Sub DrawPicture()
Dim link As String
link = "https://2ecffd01e1ab3e9383f0-07db7b9624bbdf022e3b5395236d5cf8.ssl.cf4.rackcdn.com/Product-190x190/0e72ef05-691d-4b3b-b978-a1bb9929e372.jpg"
'link = "https://pbs.twimg.com/profile_images/54789364/JPG-logo-highres.jpg"
ActiveSheet.Pictures.Insert (link)
End Sub
If someone could explain and provide a solution to this issue that would be great

Try this code
Sub Test()
Dim src As String
Dim lfn As String
src = "https://2ecffd01e1ab3e9383f0-07db7b9624bbdf022e3b5395236d5cf8.ssl.cf4.rackcdn.com/Product-190x190/0e72ef05-691d-4b3b-b978-a1bb9929e372.jpg"
lfn = ThisWorkbook.Path & "\Output.jpg"
If RequestDownload(src, lfn) Then
Cells(1).Select
ActiveSheet.Pictures.Insert lfn
End If
End Sub
Function RequestDownload(URL$, FILE$) As Boolean
Dim b() As Byte
Dim f As Integer
With CreateObject("WinHttp.WinHttpRequest.5.1")
.Open "GET", URL, False
.setRequestHeader "DNT", "1"
On Error GoTo Fin
.send
If .Status = 200 Then
b = .responseBody
f = FreeFile(1)
Open FILE For Binary As #f
Put #f, , b
Close #f
RequestDownload = True
End If
Fin:
End With
End Function

Have you tried the DisplayAlerts setting to Flase?
Sub DrawPicture()
Dim link As String
link = "https://2ecffd01e1ab3e9383f0-07db7b9624bbdf022e3b5395236d5cf8.ssl.cf4.rackcdn.com/Product-190x190/0e72ef05-691d-4b3b-b978-a1bb9929e372.jpg"
'link = "https://pbs.twimg.com/profile_images/54789364/JPG-logo-highres.jpg"
Application.DisplayAlerts = False
ActiveSheet.Pictures.Insert (link)
Application.DisplayAlerts = True
End Sub

Related

Open & Check out Excel workbook from SharePoint

I'm trying to write data into an Excel workbook that is hosted in our SharePoint document library.
I instantiate Excel from Microsoft Project.
I tried the following:
Check if file can be checked out
If it can be checked out, then open it
Here's the code snippet:
If ExcelApp.Workbooks.CanCheckOut (FileURL) = True Then
Set NewBook = ExcelApp.Workbooks.Open(FileName:=FileURL, ReadOnly:=False)
ExcelApp.Workbooks.CheckOut (FileURL)
Else
MsgBox "File is checked out in another session."
End If
The CanCheckOut function always returns FALSE. I'm not able to tell when a file can be checked out by the Excel instance.
Is it not working because I'm calling the VBA code from MS Project?
My app should be able to check if a file is not checked out, then check it out, update it, and save + check it back in.
I've found through trial and error that Workbooks.CanCheckOut (Filename:= FullName) where FullName is the URL for the SharePoint file only works for files that are not open in the current instance of Excel.
The method will always return False if you have the file open in the current instance of Excel which is obviously the case here.
Workbooks.CheckOut (ActiveWorkbook.FullName) opens the file, checks it out and then inexplicably, closes the file. So opening and checking out a SharePoint file becomes a 3 step process.
Sub CheckOutAndOpen()
Dim TestFile As String
TestFile = "http://spserver/document/Test.xlsb"
If Workbooks.CanCheckOut(TestFile) = True Then
Workbooks.CheckOut(TestFile)
Workbooks.Open (TestFile)
Else
MsgBox TestFile & " can't be checked out at this time.", vbInformation
End If
End Sub
This is all a bit counter intuitive because when working manually with SharePoint files you have to open them to see if they can be checked out and then perform the check-out operation.
Neither MSDN or Excel VBA help mention that the Workbooks.CanCheckOut (Filename:= FullName) method always returns False if you have the file open in the current instance of Excel.
The other methods never worked for me. This will CheckOut the file and either open it hidden and terminate (Visible = False), or you can just have it open (Visible = True) and remove the Quit, BUT while the doc is Checked out, I can't seem to target or check in that mXLApp doc further. The solution is to not leave the mXLApp doc open, but then once closed to open that same doc as normal, and then it will Check in with the Check in code line.
Sub TestCheckOut()
Dim FileName as String
FileName = "http://spserver/document/Test.xlsx"
SP_CheckOut FileName
End Sub
Sub SP_CheckOut(docCheckOut As String)
Set mXlApp = CreateObject("Excel.Application")
' Determine if workbook can be checked out.
' CanCheckOut does not actually mean the doc is not currently checked out, but that the doc can be checked in/out.
If mXlApp.Workbooks.CanCheckOut(docCheckOut) = True Then
mXlApp.Workbooks.Open fileName:=docCheckOut
mXlApp.Workbooks.CheckOut docCheckOut
' False is hidden
mXlApp.Visible = False
mXlApp.Quit
Set mXlApp = Nothing
Workbooks.Open fileName:=docCheckOut
Else
MsgBox "Unable to check out this document at this time."
End If
End Sub
As for Checkin, can't get any methods to work except:
Workbooks(CheckName).checkin SaveChanges:=True, Comments:=""
Sub CheckIn(CheckName As String, CheckPath As String)
' Must be open to save and then checkin
Dim wb As Workbook
On Error Resume Next
Set wb = Workbooks(CheckName)
If Err = 0 Then
WorkbookIsOpen = True
Else
WorkbookIsOpen = False
Set wb = Workbooks.Open(CheckPath)
End If
wb.CheckIn SaveChanges:=True, Comments:=""
End Sub
I did try using a Query on the SharePoint browser link to determine who has the doc checked out (if anyone). This worked sometimes. If it did work, half the time it would take too long to be useful, and the other half of the time it would throw a timeout error. Not to mention the query would disrupt other processes, like saving or certain other macros. So I put together a WebScrape which quickly returns who might have the doc checked out.
Sub TestWho()
Dim SPFilePath As String
SPFilePath = "http://teams.MyCompany.com/sites/PATH/PATH/Fulfillment/Forms/AllItems.aspx"
Debug.Print CheckedByWho(SPFilePath , "YOURdocName.xlsx")
End Sub
Function CheckedByWho(ShareFilePath As String, ShareFileName As String)
Dim ie As Object
Dim CheckedWho As String
Dim ImgTag As String
Dim CheckStart, CheckEnd As Integer
Dim SplitArray() As String
Set ie = GetObject("new:{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}")
With ie
.Visible = False
.Navigate ShareFilePath
Do Until .readyState = 4: DoEvents: Loop
Do While .Busy: DoEvents: Loop
End With
CheckedWho = "Not Check Out"
For Each objLink In ie.document.getElementsByTagName("img")
ImgTag = objLink.outerHTML
CheckedOutPos = InStr(objLink.outerHTML, ShareFileName & "
Checked Out To:")
If CheckedOutPos > 0 Then
CheckStart = InStr(objLink.outerHTML, "Checked Out To: ")
CheckedWho = Mid(objLink.outerHTML, CheckedOutPos + 41)
SplitArray = Split(CheckedWho, """")
CheckedWho = SplitArray(0)
End If
Next objLink
CheckedByWho = CheckedWho
ie.Quit
End Function

Selenium Basic VBA focus on new tab that is opened by Click

I'm working on the Selenium Basic Wrapper for Excel VBA, but upon clicking a button that opens a new tab, I am unable to get the selenium web-driver to switch focus onto the new tab that is opened, and to close the original tab.. Believe this should be achievable using the Java Selenium, but is there any way to do it through the Selenium Basic wrapper on excel VBA?
Have tried using bot.switchtopreviouswindow/nextwindow to no avail, Selenium does not even seem to detect the new tab/window opened as an existing window, also tried using switchwindow using title to no avail...
Private Sub CommandButton1_Click()
Dim bot As New ChromeDriver
Dim merchant As String
Dim promocode As Object
Dim number As Long
Dim test As Object
Dim testnumber As Integer
lastColumn = Sheets("Merchants").Range("B" & Rows.Count).End(xlUp).Row
For i = 2 To lastColumn
bot.Get (Sheets("Merchants").Range("B" & i).Value)
merchant = Sheets("Merchants").Range("A" & i).Value
For Each promocode In bot.FindElementByClass("main_vouchers").FindElementsByClass("c")
number = Right(promocode.Attribute("id"), 6)
If IsEmpty(promocode) = True Then Exit For
promocode.FindElementByClass("go").Click
#This is the part I have problems with as after click, original page re-directs to another page, and new tab opens (which is the place I want focus on). Also, I need the original tab closed so that Chrome doesn't end up opening too many tabs due to the loop running. Appreciate the help!
Next promocode
Next i
End Sub
Just need Selenium to switch focus onto newly opened tab and for old/original tab to be closed..
The following works for me where you use switchToNextWindow and then you take 1 off the current window count (you might want to check more .windows.count > 1 first), and close that item in windows collection.
You can also .SwitchToWindowByName and .SwitchToWindowByTitle if either of those are known in advance | can be extracted from the current page.
'Ensure latest applicable driver e.g. ChromeDriver.exe in Selenium folder
'VBE > Tools > References > Add reference to selenium type library
Public Sub Example()
Dim d As WebDriver
Set d = New ChromeDriver
Const URL = "https://www.cuponation.com.sg/agoda-discount-code"
With d
.get URL
Debug.Print .Window.Title
.FindElementByCss(".go").Click
.SwitchToNextWindow
Debug.Print .URL '<= includes voucher code
'do something with new window
Debug.Print .Window.Title
.Windows.item(.Windows.Count - 1).Close 'close prior window
Debug.Print .Window.Title
Stop
.Quit
End With
End Sub
Sub DownloadFileFromLaquintaca2()
Dim cd As New selenium.ChromeDriver
Dim DefaultChromeDownloadFolder As String
Dim MyURL As String
' Start Chrome
Set cd = New ChromeDriver
cd.Start
' Navigate to
cd.get "https://www.laquintaca.gov/connect/short-term-vacation-rentals"
Const URL = "https://www.cuponation.com.sg/agoda-discount-code"
Dim FindBy As New selenium.By
Dim imgElement As selenium.WebElement
' Check if element is present with CSS
If Not cd.IsElementPresent(FindBy.Css("img[alt='ACTIVE & SUSPENDED PERMITS BOX']")) Then
MsgBox "Could not find image box"
Exit Sub
End If
cd.FindElementByCss("img[alt='ACTIVE & SUSPENDED PERMITS BOX']").Click
Application.Wait (Now + TimeValue("0:00:3"))
'Get URL Address in Second Chorme Tab
With cd
.get URL
.SwitchToNextWindow
MyURL = .URL
'Debug.Print .Window.Title
'Debug.Print myURL
.Windows.Item(.Windows.Count - 1).Close 'close prior window
End With
'Write PDF File into Location with file Name STVR.PDF ---D:\MyDownLoads\STVR.pdf
Dim WinHttpReq As Object
Set WinHttpReq = CreateObject("Microsoft.XMLHTTP")
WinHttpReq.Open "GET", MyURL, False, "username", "password"
WinHttpReq.send
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.responseBody
oStream.SaveToFile "D:\MyDownLoads\STVR.pdf", 2 ' 1 = no overwrite, 2 = overwrite
oStream.Close
End If
End Sub

hyperlinks(1).address only returning a partial address

I'm working on the following code, which will re-format a cell containing a link based on whether or not the link works when it is clicked:
Private Sub worksheet_followhyperlink(ByVal HL As HYPERLINK)
Dim linkReq As Object
Dim linkStatus As Integer
Application.ScreenUpdating = False
On Error GoTo linkError
Set linkReq = New MSXML2.XMLHTTP60
With linkReq
.Open "GET", HL.address, False
.Send
End With
linkStatus = linkReq.Status
If linkStatus = 404 Then HL.Parent.Interior.Color = rgbPink
If linkStatus <> 404 Then HL.Parent.Interior.Pattern = xlNone
If HL.Parent.Interior.Pattern = xlNone Then GoTo exitSub
Application.ScreenUpdating = True
MsgBox("Link is broken")
exitSub:
Application.ScreenUpdating = True
Exit Sub
linkError:
linkStatus = 404
Resume Next
End Sub
The code worked great yesterday! But now, it's returning everything as '404' and marking the cells pink, even if the links work. Debugging reveals that the value of HL.address is "folder/Document.pdf" instead of "https://website/folder/Document.pdf". This excel document is hosted on "https://website" through sharepoint.
The code not working because of the truncation.
Is there a way to extract a full url from an excel hyperlink, without truncation, regardless of the size of the url?
It seems that Excel is changing your hyperlinks adresses from absolute to relative.
You can try to force absolute adress by changing so called "Hyperlink Base". In order to do it go to: File > Info > Show All Properties > Hyperlink Base (on the right of screen) and change it to "x".
Reference from Microsoft Support site:
https://support.microsoft.com/en-us/help/903163/how-to-create-absolute-hyperlinks-and-relative-hyperlinks-in-word-docu
(Article presents solution for MS Word but it should work in MS Excel as well)
Hope that helps.
The range object in excel has a second property "Subaddress" .
Use the Subaddress functionality to get the rest of the address like below
range.Hyperlinks(1).Address + range.Hyperlinks(1).SubAddress
In my case I had to add additional characters in between Address and Subaddress. Please make sure to check how the full URL can be formed using both Address and Subaddress

Excel VBA: get error code for invalid URL in hyperlink with WinHttpRequest

In Excel, I have a list with URLs. I need to check if IE (default browser) can open these. They don't have to open actually, it's to check the accessibility.
If they can't open, I need to isolate the error-code and place that in another column.
After searching around here, I started with following the hyperlinks, and used GET to get the data in a MsgBox. This seems to work partially, but of course now I get the MsgBox with every URL also without error. Also I'm looking for a way to extract the error and place that in the active sheet.
What I've got so far:
Sub Request_Data()
' declare
numRow = 2
Dim MyRequest As Object
' activate URLs without Follow
Do While ActiveSheet.Range("C" & numRow).Hyperlinks.Count > 0
numRow = numRow + 1
' create request
Set MyRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
MyRequest.Open "GET", _
ActiveSheet.Range("C" & numRow)
' send request
MyRequest.Send
' outcome
MsgBox MyRequest.ResponseText
' isolate the error code (for example 404)
' place error code in excel sheet in column H next to row URL
Loop
End Sub
Does someone know how I should proceed?
I thought this might be useful but I don't know where to start.
Checking for broken hyperlinks in Excel
and
Bulk Url checker macro excel
Thanks in advance
See the code below - you will need to adapt the Test sub-routine to loop through your cells and call IsValidUrl for each value you want to test:
Option Explicit
Sub Test()
MsgBox IsValidUrl("http://www.thisdoesnotexistxxxxxxxxxxxxx.com/")
MsgBox IsValidUrl("http://www.google.com/")
MsgBox IsValidUrl("http://www.ppppppppppppqqqqqqqqqqqqqqrrrrrrrrrrrrr.com/")
End Sub
Function IsValidUrl(strUrl As String) As Long
Dim objRequest As Object
Dim lngCode As Long
On Error GoTo ErrHandler
Set objRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
With objRequest
.Open "GET", strUrl
.Send
lngCode = 0
End With
GoTo ExitHandler
ErrHandler:
lngCode = Err.Number
ExitHandler:
Set objRequest = Nothing
IsValidUrl = lngCode
End Function
My output is:
-2147012889
0
-2147012889

Insert reference to page number in Microsoft Publisher 2010

I am new to MS Publisher 2010, and I am trying to add a "dynamic" reference to a specific page. Ideally, the visualized text should be something like:
...see the example on page XXX
I would like to make the XXX part visualize the page number of the page I am referring to. I saw that you can place bookmarks in the document, and create hyperlinks to those bookmarks, but so far I could not manage to visualize the page number tied to a bookmark.
To make another example, I would like the equivalent of this Latex expression:
...see the example on page~\pageref{reference-to-XXX}
Would it be possible to obtain this effect in Publisher 2010, maybe using a VB script? Thank you for your help!
http://answers.microsoft.com/en-us/office/forum/office_2007-office_other/how-do-i-hyperlink-specific-text-within-the-same/598cfd98-6217-4eac-9ac9-969477c46401?auth=1
"This is fairly easy with Pub 2007. Just Insert > bookmark and drag that icon to where you want the link to go. Then select the text >insert hyperlink > place in this document and choose the bookmark that you just created. The only time I have had problems is if the page is not long enough below the bookmark...and there are workarounds.
http://office.microsoft.com/en-us/publisher-help/create-a-hyperlink-HP010203490.aspx
DavidF"
Let me know if this helps or if you for some reason need to do it in VBA
Edit:
It is fairly easy to write a macro to refresh links to pages, but links to bookmarks seem to be poorly supported by the object model, unless I've overlooked something. My solution consists of two parts.
First of all, links that should be refreshed are recognised by their display text starting with "page " (LIKE "page *"). The refresh macro simply recognizes those links and changes their display text to page X. However, this doesn't work for links to bookmarks, which in the object model seem to behave like links to pages, except the pageID they refer to does not exist. I spent quite a while trying to figure out what the relationship might be between this non-existent hyperlink and the bookmark, but to no avail. Instead I've created a workaround in which you manually link the hyperlink and the bookmark with a tag object (creating a tag for the bookmark with the value of the non-existent page ID of the hyperlink).
Instructions for normal links to pages
Create a hyperlink to a page. The text of it must begin with ”page ”
(otherwise RefreshReferenceLinks must be edited)
Run C_RefreshReferenceLinks to refresh to check that it worked
Instructions for links to bookmarks (tagging workaround)
Create a bookmark (Insert -> Bookmark)
Create a hyperlink to the Bookmark
Select the hyperlink and run A_GetPageIdOfHyperlink
Select the bookmark and run B_TagBookmarkWithPageId
Run C_RefreshReferenceLinks to refresh to check that it worked
You can download my example project containing example content, instructions, and the macros below here: http://www.filedropper.com/showdownload.php/pageandbookmarklinks (it will probably give you a security warning because it contains macros)
Full source
Public Const tagName = "BookmarkPageId"
Sub A_GetPageIdOfHyperlink()
Dim oHyperlink As Hyperlink
Set oHyperlink = ActiveDocument.Selection.TextRange.Hyperlinks(1)
CopyText oHyperlink.pageId
MsgBox oHyperlink.pageId & " copied to clipboard as text"
End Sub
Sub B_TagBookmarkWithPageId()
Dim oShape As Shape
Set oShape = ActiveDocument.Selection.ShapeRange(1)
If IsBookmark(oShape) Then
If TagExists(oShape.Tags, tagName) Then
oShape.Tags(tagName).Delete
End If
Dim txt As String
txt = Trim(GetClipBoardText())
Debug.Print "Ssdsd:" & txt
Dim newTag As Tag
Set newTag = oShape.Tags.Add(tagName, txt)
MsgBox "Tagged as " & tagName & " = '" & txt & "'"
Else
MsgBox "Not a bookmark"
End If
End Sub
Sub C_RefreshReferenceLinks()
Dim oPage As Page
Dim oShape As Shape
For Each oPage In ActiveDocument.Pages
For Each oShape In oPage.Shapes
RefreshInShape oShape
Next oShape
Next oPage
For Each oPage In ActiveDocument.MasterPages
For Each oShape In oPage.Shapes
RefreshInShape oShape
Next oShape
Next oPage
For Each oShape In ActiveDocument.ScratchArea.Shapes
RefreshInShape oShape
Next oShape
End Sub
Function RefreshInShape(oShape As Shape)
Dim cHyperlinks As Hyperlinks
Dim oHyperlink As Hyperlink
If oShape.HasTextFrame = False Then Exit Function
Set cHyperlinks = oShape.TextFrame.TextRange.Hyperlinks
For i = 1 To cHyperlinks.Count
Set oHyperlink = cHyperlinks(i)
If oHyperlink.TargetType = pbHlinkTargetTypePageID Then
If oHyperlink.TextToDisplay Like "page *" Then
oHyperlink.TextToDisplay = "page " & GetPageNumberByPageId(oHyperlink.pageId)
End If
End If
Next i
End Function
Function GetPageNumberByPageId(pageId)
Dim oPage As Page
Dim oShape As Shape
Dim oTag As Tag
For Each oPage In ActiveDocument.Pages
If CLng(oPage.pageId) = CLng(pageId) Then
GetPageNumberByPageId = oPage.PageNumber
Exit Function
End If
Next oPage
For Each oPage In ActiveDocument.Pages
For Each oShape In oPage.Shapes
If TagExists(oShape.Tags, tagName) Then
Set oTag = oShape.Tags(tagName)
If CStr(oTag.Value) = CStr(pageId) Then
GetPageNumberByPageId = oPage.PageNumber
Exit Function
End If
End If
Next oShape
Next oPage
GetPageNumberByPageId = "[ERROR]"
End Function
Function IsBookmark(oShape As Shape)
IsBookmark = False
If oShape.Type = pbWebHTMLFragment And oShape.AutoShapeType = msoShapeMixed Then
IsBookmark = True
End If
End Function
Function TagExists(collection As Tags, itemName As String) As Boolean
TagExists = False
Dim oTag As Tag
For Each oTag In collection
If oTag.Name = itemName Then
TagExists = True
Exit For
End If
Next oTag
End Function
Function GetParentOfType(obj As Object, sTypeName As String)
Do Until TypeName(GetParentOfType) = "Page"
Set GetParentOfType = obj.Parent
Loop
End Function
Sub CopyText(Text As String)
'VBA Macro using late binding to copy text to clipboard.
'By Justin Kay, 8/15/2014
'Thanks to http://akihitoyamashiro.com/en/VBA/LateBindingDataObject.htm
Set MSForms_DataObject = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
MSForms_DataObject.SetText Text
MSForms_DataObject.PutInClipboard
Set MSForms_DataObject = Nothing
End Sub
Function GetClipBoardText() As String
Set DataObj = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
On Error GoTo Whoa
'~~> Get data from the clipboard.
DataObj.GetFromClipboard
'~~> Get clipboard contents
GetClipBoardText = DataObj.GetText(1)
Exit Function
Whoa:
GetClipBoardText = ""
End Function

Resources