I would like to automatically print a QR code from one of my cells. The best way to do this that I've found is using the IMAGE function.
The function looks like this:
=IMAGE("https://api.qrserver.com/v1/create-qr-code/?data="&ENCODEURL(B2))
Unfortunately, sometimes when I print after changing the value of my cell it prints before the QR Code is generated and I get something like this: The PrintPreview shows a text string of "Picture" where the QR code should be
I have tried several methods to get the function to finish, but none have been reliable.
Sub ChangePrintedQR()
Dim ImgRange As Range
Set ImgRange = Range("B4")
Range("B2") = Now
' ImgRange.Formula = "=IMAGE(""https://api.qrserver.com/v1/create-qr-code/?data=""&ENCODEURL(B2))" 'Having this line can print "Busy" instead of "Picture"
' While ImgRange.Text = "Picture" 'This gets stuck in an infinite loop
' Debug.Print ImgRange.Text 'regardless of this line, trying the Value of the cell does the same
' Wend
' Application.Calculate 'This method does nothing
' If Not Application.CalculationState = xlDone Then
' DoEvents
' End If
' Application.Wait (Now + TimeValue("0:00:10")) 'This results in the waiting, but no change to the printed sheet.
ActiveSheet.PrintPreview
End Sub
Please note that I sometimes have gotten an updated Image when printing, but not other times, I would like to be able to print an updated Image every time.
Okay… After some testing, this appears to be one of the times when DoEvents
is insufficient, and you need to allow code to fully end. To make this work, you can use the OnTime
function, and split the function in two:
Option Explicit
Private imgRange AS Range
Sub ChangePrintedQR()
Set ImgRange = Range("B4")
ImgRange.Formula = "=IMAGE(""https://api.qrserver.com/v1/create-qr-code/?data=""&ENCODEURL(B2))"
ImgRange.Calculate
Application.OnTime Now(), "PreviewPrintedQR"
End Sub
Sub PreviewPrintedQR()
If ImgRange.Value = CVErr(2051) Then
Application.OnTime Now() + TimeSerial(0, 0, 1), "PreviewPrintedQR"
Else
Set ImgRange = Nothing
ActiveSheet.PrintPreview
End If
End Sub
This will add one-second delays, and fully halt the VBA between loops — this allows the image to be downloaded and change the cell from #BUSY
to #VALUE
.
(There may be a way to force/allow the connection/download to occur during VBA and turn this back into a single function, however I had no success with Refreshing Connections, Refreshing Links, DoEvents
, etc)