Analistable

Which orders were refunded but still shipped?

By the Analistable team · Updated · 3 min read

Join the refunds export to the shipments export on order ID and compare dates. Orders shipped on or after the refund date were sent for free unless the refund was partial or the parcel was recalled. In the example, O-311 and O-315 shipped a day after being refunded.

Part of our guide: How to answer questions across multiple spreadsheets

The data

Refunds and shipments
Refund: orderRefunded onAmountShipment: orderShipped onCarrier
O-3102026-09-0345O-3102026-09-02DPD
O-3112026-09-0430O-3112026-09-05Royal Mail
O-3152026-09-0660O-3122026-09-05DPD
O-3152026-09-07DPD

In a spreadsheet

Shipped on =XLOOKUP([@Order], Shipments[Order], Shipments[Shipped on], "")
Flag       =IF([@[Shipped on]] = "", "Not shipped",
            IF([@[Shipped on]] >= [@[Refunded on]], "Shipped after refund", "Shipped before refund"))

In SQL

SELECT r.order_id, r.refunded_on, s.shipped_on,
       CASE WHEN s.shipped_on >= r.refunded_on THEN 'shipped after refund'
            ELSE 'shipped before refund' END AS flag
FROM refunds r
JOIN shipments s ON s.order_id = r.order_id;
Result
order_idrefunded_onshipped_onflag
O-3102026-09-032026-09-02shipped before refund
O-3112026-09-042026-09-05shipped after refund
O-3152026-09-062026-09-07shipped after refund

O-310 shipped before the refund — probably a return, which is normal. O-311 and O-315 shipped after the refund: the warehouse didn't get the cancellation in time.

Follow-up checks

  • Compare the refund amount with the order total: a partial refund (for a missing item) followed by shipping can be legitimate.
  • Group the after-refund cases by warehouse or carrier cut-off time to find where cancellations get lost.
  • Use timestamps rather than dates if you have them — a same-day refund and shipment needs the time to tell which came first.

Ask it in Analistable: “Which refunded orders shipped on or after the refund date, and what were they worth?”

Putting a value on it

Sum the order value (or cost of goods) for the “shipped after refund” rows each month. In the example that's 30 + 60 = 90 in refunds on goods that still went out. Over a year, the total usually justifies fixing the cancellation hand-off, for example an automatic hold on refunded orders in the warehouse system.

Excel 2019 and Google Sheets

Shipped on =IFERROR(INDEX(Shipments!B:B, MATCH(A2, Shipments!A:A, 0)), "")
=FILTER(Refunds!A2:B, IFERROR(VLOOKUP(Refunds!A2:A, Shipments!A2:B, 2, FALSE), 0) >= Refunds!B2:B)

The INDEX/MATCH version works in any Excel version, on Windows or Mac. The Google Sheets formula lists refunded orders whose ship date is on or after the refund date; refunds with no shipment become 0 and drop out. Both assume the dates are real dates — text dates compare alphabetically, which only works for the ISO format.

Same-day cases need timestamps

Order refunded and shipped on 8 September
OrderRefunded atShipped atVerdict
O-3202026-09-08 09:152026-09-08 16:40Shipped after refund
O-3212026-09-08 17:052026-09-08 11:30Shipped before refund

On dates alone both rows match the “on or after” rule. With times, only O-320 is a real miss: the refund was issued in the morning and the parcel still left in the afternoon. O-321 was probably refunded after the customer complained about a parcel already on its way.

Troubleshooting

When the join returns nothing or too much
SymptomCauseFix
No matches at allOrder IDs formatted differently (#1001 vs 1001)Strip prefixes and convert to the same type
One refund matched to several shipmentsSplit shipments under the same orderUse the earliest or latest ship date per order
Many “after refund” returnsReturn labels exported as shipmentsFilter shipments to outbound only

Make it a weekly check

  • Export refunds and shipments for the same date range, with a few days' overlap at each end so late shipments are caught.
  • Keep a running list of flagged orders with the outcome (recalled, customer kept goods, re-charged) — the recovery rate shows whether chasing is worth it.
  • For the money side of refunds, see reconciling Shopify orders with Stripe payouts.

Frequently asked questions

How do I find refunded orders that shipped?
Join refunds to shipments on order ID and flag rows where the ship date is on or after the refund date.
What if refunds and shipments are in different systems?
Export both with the order ID, make sure the IDs use the same format, and join on it.
Are all of these losses?
Not always — partial refunds and recalled parcels are legitimate. Check the amount and status before chasing.
Do I need timestamps?
Only for same-day cases. Dates are enough for most orders, but a refund and shipment on the same day need times to tell which came first.
Can I check this before goods leave?
Yes: run the join on refunds against orders still awaiting dispatch, and hold any match.
What about split shipments?
Use the latest ship date per order, or flag each parcel separately.

Related guides