All guides
Data quality

How to handle duplicate QR scans in Google Sheets

Record every scan, flag the repeat, dedupe in the sheet: UNIQUE, COUNTIFS and QUERY formulas for a clean tab, and why refusing a repeat scan loses data.

8 min readUpdated 1 October 2026

Short answer

In Google Sheets, a duplicate QR scan is best recorded and flagged rather than refused, because a scan that was thrown away cannot be told apart from one that never happened.

Keep the raw scan log untouched and build a deduplicated tab with UNIQUE, COUNTIFS or QUERY that keeps each code's first scan per day.

A Google Form cannot warn the person scanning; QR to Sheets writes every scan and shows an amber Saved anyway badge when the same code repeats on a link within 12 hours.

Duplicate scans come from three different places, and only one of them is a mistake. A code sitting in front of the camera gets read again as a phone passes over it. A person is not sure the first scan registered and scans again. And sometimes a person or an item genuinely comes back: a second entry after lunch, a tool going out twice in one day, two units of the same product on a shelf.

Those three need three different answers, and at the moment of scanning nothing can reliably tell them apart. That is why the useful question is not how to stop duplicates, but where to decide what they mean. The answer this guide argues for: record everything, flag the repeat at the time, and make the decision in the spreadsheet.

Written by QR to Sheets, so read the product section as vendor material. The formulas below work on any sheet of scan rows, whichever tool wrote them, including a Google Form's response sheet.

Why refusing a repeat scan is the wrong default

A system that silently rejects the second scan feels tidy, and it destroys information. Afterwards you cannot tell a person who scanned once from a person whose second scan was thrown away, and you cannot recover the genuine second trip that the rule happened to swallow. If a record is ever disputed, a complete log is evidence; a log with rejected rows missing is an argument.

Recording and flagging keeps the log complete and moves the judgement to the one place it can be changed later without losing anything. If you decide next month that a second scan within ten minutes should count as the same visit, you change a formula. If the scanner had refused it, that data would simply not exist.

The free route: a Google Form, then formulas

A Google Form behind a printed QR code writes every submission to a linked Google Sheet, duplicates included. That is the right behaviour for the log, and it costs nothing. The form's Limit to 1 response setting is not a duplicate filter for this job: Google's own help states that it requires respondents to sign in to their Google Account, so it limits accounts rather than codes and adds a sign-in step to every scan.

Formulas that build a deduplicated tab

These assume the timestamp is in column A and the scanned value in column B, which is the default QR to Sheets row and close to most form layouts. Adjust the letters to your own sheet, and make sure the timestamp column holds real dates rather than text, or every date comparison below silently fails.

Google Sheets also has Data, Data cleanup, Remove duplicates. It deletes the repeated rows from the range you select, so it belongs on a copy of the data, never on the tab your scans land in.

Where the free route breaks

What QR to Sheets does with a repeat scan

This is the product we make, so treat it as one design rather than a claim about every tool. It separates the accidental repeat from the deliberate one. A code held in front of the camera is accepted once; it has to leave the frame before the scanner will take it again, so a phone resting over a badge does not write a row every second.

A code scanned again on purpose is always written. When the same value repeats on the same scanner link within 12 hours, the screen turns amber, says Already scanned with the number of times on this link, and adds Saved anyway. The scan is never blocked, and if the repeat check is unavailable for any reason the scanner simply shows no badge and carries on. The window is per link, so a code scanned on a Check out link and then on a Check in link does not warn.

Two quieter behaviours matter for duplicates too. A scan resent after a dropped connection is not written twice, so a flaky signal does not double your rows. And each scan is saved on the phone first, so the worker does not rescan out of doubt when the network is slow.

Google Forms + formulas (free) compared with QR to Sheets
CapabilityGoogle Forms + formulas (free)QR to Sheets
CostFreeFree for 300 scans, then 7 USD per registered device per month
Warning when a code repeatsNoneAmber Already scanned badge with the count, and Saved anyway
Repeat windowNot applicable12 hours, counted per scanner link
Code left in front of the cameraNot applicable, no camera scannerAccepted once; it must leave the frame first
Resent after a dropped connectionSubmission lost, often retypedNot written twice
Is the repeat row writtenYesYes, always
Deduplicated registerFormulas you writeFormulas you write

Which scan should count?

Step by step

  1. 1

    Decide what a repeat means in your workflow

    For attendance, a second scan the same day is usually noise. For check-out, it may be a genuine second trip. For a stock count, it may be a second unit of the same product. Write the rule down before you write a formula.

  2. 2

    Leave the raw log alone

    Never delete rows from the tab your scans land in. Every report, including the deduplicated one, is a view built on top of it, so a wrong formula can always be fixed and a disputed record can always be checked.

  3. 3

    Add a date column and a first-scan flag

    A helper column holding the date of each scan, and a running COUNTIFS that marks the first occurrence of each code on each date, gives you a TRUE/FALSE you can filter, pivot and count on.

  4. 4

    Build the clean tab from the flag

    A FILTER or QUERY over the log that keeps only first scans is the deduplicated register. It updates itself as new rows arrive, so nobody has to clean the data by hand.

  5. 5

    Tell the people scanning what a warning means

    If your scanner shows a repeat warning, say in the same message as the link that the scan was still saved and that nobody needs to rescan. Most real-world duplicates come from people who were not sure the first scan worked.

Frequently asked questions

How do I remove duplicate QR scans in Google Sheets?+

Do not remove them from the log. Add a date column and a first-scan flag with COUNTIFS, then build a separate tab with FILTER or QUERY that keeps only first scans. The raw log stays complete and the clean tab updates itself as new scans arrive.

Does QR to Sheets block a duplicate scan?+

No. Every deliberate scan is saved. A repeat of the same value on the same link within 12 hours shows an amber badge with the repeat count and the words Saved anyway, so the person scanning knows without anything being refused. A code held in front of the camera is only accepted once until it leaves the frame.

Will scanning someone in and out trigger the repeat warning?+

Not if you use two scanner links, one for each direction, which is the recommended setup anyway. The repeat window is counted per link, so the same badge scanned on a Check in link and then a Check out link does not warn.

Can a Google Form stop someone submitting twice?+

Only by account. The Limit to 1 response setting requires respondents to sign in to their Google Account, so it limits each account to one response. It cannot recognise the same code submitted twice, and it adds a sign-in step that most scanning workflows cannot afford.

Why do I see the same code twice a few seconds apart?+

Usually because the person scanning was not sure the first scan worked, or the code was typed and pasted twice. Clear success feedback on the scanner and a note in the instructions that a scan does not need repeating remove most of them. Treat pairs seconds apart as one event in your formulas.

What formula keeps only the first scan per person per day?+

With timestamps in column A, codes in column B and the date of each scan in column G, put =COUNTIFS($B$2:B2, B2, $G$2:G2, G2)=1 in the first data row of a new column and fill it down. It is TRUE for the first scan of each code on each date. Filter on TRUE.

Try it on your own Google Sheet

Connect Google, create a scanner link, and share the URL with your team. The free tier covers 300 scans, and nobody you share it with has to install anything.

Start for free

No credit card required

Keep reading