# Generate a QR code in Excel VBA

> Shapes.AddPicture accepts a URL directly, so one VBA call places a QR code from the keyless API onto the sheet, no download step. Encode cell values with Application.WorksheetFunction.EncodeURL, loop a range to make a code per row, and use URLDownloadToFile when you need the PNG on disk.

Source: https://useqr.app/docs/developers/generate-a-qr-code-in-excel-vba · Last reviewed 2026-08-21 · UseQR is free forever, no signup.

---

## Check the no-code route first

Excel 365's `IMAGE()` function puts a QR code in a cell with a formula and no macro
security prompts, if that is available to you, start with
[how to make a QR code in Excel](/docs/how-to/how-to-make-a-qr-code-in-excel). VBA earns
its keep on older Excel versions, for placing codes as positioned shapes, and for batch
jobs that also write files.

## One shape, one call

`Shapes.AddPicture` takes a URL as its filename argument, so the
[keyless API](/docs/developers/free-qr-code-api-no-key) needs no download step at all:

```vb
Sub AddQr()
    Dim ws As Worksheet: Set ws = ActiveSheet
    ws.Shapes.AddPicture _
        "https://useqr.app/api/v1/qr?data=" & _
        Application.WorksheetFunction.EncodeURL("https://example.com") & "&size=512", _
        msoFalse, msoTrue, ws.Range("C2").Left, ws.Range("C2").Top, 96, 96
End Sub
```

The arguments after the URL: `LinkToFile:=msoFalse, SaveWithDocument:=msoTrue` embeds the
image in the workbook, then left, top, width and height in points (96 pt ≈ 3.4 cm, around
the [2 × 2 cm print floor](/docs/print/qr-code-size-for-print) once margins are considered,
so size up if the sheet will be printed).

`Application.WorksheetFunction.EncodeURL` (Excel 2013+) is the important part: a raw `&`
in a cell's URL would otherwise start a new query parameter and silently truncate the
code's payload.

## A code for every row

```vb
Sub QrForRange()
    Dim ws As Worksheet: Set ws = ActiveSheet
    Dim cell As Range, url As String
    For Each cell In ws.Range("A2:A101")
        If Len(cell.Value) > 0 Then
            url = "https://useqr.app/api/v1/qr?data=" & _
                  Application.WorksheetFunction.EncodeURL(CStr(cell.Value)) & "&size=512"
            ws.Shapes.AddPicture url, msoFalse, msoTrue, _
                cell.Offset(0, 1).Left, cell.Offset(0, 1).Top, 96, 96
        End If
    Next cell
End Sub
```

Each shape lands beside its source cell. The API's responses are deterministic and
cacheable, so re-running the macro is cheap, but delete the old shapes first or they
stack. Larger spreadsheet-to-labels workflows (mail merge, label sheets) are mapped out in
[QR codes from a spreadsheet](/docs/how-to/how-to-make-qr-codes-from-a-spreadsheet).

## Saving PNGs to disk

When the deliverable is files rather than shapes, declare `URLDownloadToFile` (Windows
only. It lives in urlmon.dll):

```vb
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" _
    Alias "URLDownloadToFileA" (ByVal pCaller As LongPtr, ByVal szURL As String, _
    ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As LongPtr) As Long

Sub SaveQr()
    URLDownloadToFile 0, "https://useqr.app/q/hello.png", "C:\qr\hello.png", 0, 0
End Sub
```

For print-quality output, request `size=1024` or more, or `format=svg` if the downstream
tool takes vector, a 96 px PNG enlarged later will be
[blurry on paper](/docs/troubleshooting/qr-code-blurry-when-printed).

Two honesty notes: on a Mac, `URLDownloadToFile` is unavailable (the AddPicture route
still works), and payloads containing credentials should not go through any web API:
Excel is the wrong tool for WiFi-password codes; use an
[offline generator](/docs/security/client-side-vs-server-side-qr-generation) instead. The
Google-side equivalent of this page is
[Apps Script](/docs/developers/generate-a-qr-code-in-google-apps-script).

## FAQ

### How do I insert a QR code with VBA?
Call Shapes.AddPicture with the keyless API URL as the filename argument. Excel fetches the image itself; no download code is required.

### How do I encode the cell value safely?
Wrap it in Application.WorksheetFunction.EncodeURL before concatenating into the API URL. Unencoded ampersands truncate the payload silently.

### Can I make a QR code for every row?
Yes: loop the range, build the URL from each cell, and AddPicture next to it. Delete previous shapes before re-running or they pile up.

### Is there a way without macros?
In Excel 365, the IMAGE() function does the same job as a formula, which also avoids macro security warnings when sharing the workbook.

## Try it

- https://useqr.app/url
- https://useqr.app/json
- https://useqr.app/validate
