Wholesale line sheet from your own Shopify or WooCommerce store: photo, SKU, RRP, wholesale price and an order column for each product, in one Google Sheet
What you get: a wholesale line sheet in one Google Sheet, built from your own web shop. It has one row per product: photo, product name, SKU, category, sizes or colours, in stock, RRP (your normal shop price, even if a sale is running), a wholesale price worked out from one setting, the retailer's margin, a case pack and an order quantity column the shop buyer fills in, with a line total. Hide the rows you don't offer wholesale, download it as a PDF, and send it to the gift shops, boutiques and stockists you pitch for Christmas. Formulas are below. The example rows are made up.
The finished sheet
linesheet tab (example rows are made up; settings: wholesale = 50% of RRP ex VAT, shop prices include 20% VAT)
| Photo | Product | SKU | Category | Options | In stock | RRP | Wholesale ex VAT | Retailer margin | Case pack | Order qty | Line total |
|---|---|---|---|---|---|---|---|---|---|---|---|
| (image) | Hand-poured soy candle, fig | CAN-FIG-200 | Candles | 200 g, 400 g | Yes | 24.00 | 10.00 | 50% | 6 | 12 | 120.00 |
| (image) | Linen tea towel, sage | TT-SAGE | Kitchen | Yes | 18.00 | 7.50 | 50% | 6 | 8 | Order in multiples of 6 | |
| (image) | Ceramic mug, speckled | MUG-SPK | Kitchen | Blue, Sand | No | 21.60 | 9.00 | 50% | 4 |
The mug row shows why RRP is not simply "price": if the mug is on sale at 16.00 in your shop with a compare-at price of 21.60, the sheet uses 21.60, so a pre-Black-Friday sale does not cut your wholesale prices.
Who this is for
Small brands that already sell online (candles, ceramics, prints, cards, skincare, clothing, food gifts) and want to sell to independent shops too. Shop buyers usually ask for a line sheet or wholesale price list before they order. Building it by hand means copying every product, photo and price from your shop; this sheet reads them from one product file and updates when you re-import.
Step 1: get your products into a tab named scrape
With the product data scraper
Open the E-commerce Product Data Scraper (Shopify, WooCommerce, any shop) on the Apify Store and use this input with your own shop address:
{
"startUrls": [{ "url": "https://your-shop.example" }],
"maxProductsPerShop": 2000,
"includeDescription": false
}
maxProductsPerShop: set it above your number of products (the default is 100). You pay only for products delivered.includeDescription: a line sheet does not need the long description, so you can switch it off to keep the file small.- The scraper follows robots.txt and reads your shop's terms page. If your own terms forbid automated access (Shopify's default terms do), it skips the shop and charges nothing. Check the run's Storage → Key-value store →
SHOPS_SUMMARY: your shop should showok. If it showsblocked-by-terms, use your admin export below.
In the run, export the dataset as CSV. In your Google Sheet use File → Import → Upload, "Insert new sheet", and name the tab scrape. Do not rename headers. You get one row per product with columns such as title, sku, category, price, compareAtPrice, inStock, currency and images/0, and for Shopify shops variants/0/title, variants/1/title and so on. For Shopify shops, price, compareAtPrice and sku come from the cheapest variant, and category is the product type. For WooCommerce shops, category is the product's categories joined by commas, compareAtPrice is the regular price, and there are no variant columns.
Free, from your own shop admin
- Shopify: Products → Export gives one row per variant with columns such as Title, Type, Variant SKU, Variant Price, Variant Compare At Price and Image Src. Extra variant rows have an empty Title.
- WooCommerce: the built-in product CSV exporter (Products → Export) gives name, SKU, categories, regular price, sale price, stock and image columns.
The formulas below look columns up by header name, so with an admin export you change only the header names in quotes.
Step 2: the settings tab
Add a tab named settings:
| Cell | What to type | Example |
|---|---|---|
| B1 | Wholesale price as a share of RRP before VAT | 50% |
| B2 | VAT or sales tax included in your shop prices (type 0% if your shop prices exclude tax) | 20% (UK standard rate) |
| B3 | Default case pack (minimum per product) | 6 |
| B4 | Minimum first order value | 150 |
50% is only an example. Many shops price at about double their cost, but the right figure depends on your sector, your costs and what your stockists expect, so check your own numbers before you send the sheet. Wholesale prices to businesses are normally quoted before VAT; that is why the sheet takes VAT out of your shop price first.
Step 3: build the linesheet tab
Add a tab named linesheet. Row 1 holds the headers below; row 2 holds the formulas, which you copy down one row per row of scrape. Set the row height to about 100 pixels so the photos show.
| Col | Header | Formula (row 2) |
|---|---|---|
| B | Product | =IFERROR(INDEX(scrape!$A2:$ZZ2, MATCH("title", scrape!$A$1:$ZZ$1, 0)), "") |
| C | SKU | same pattern with "sku" |
| D | Category | same pattern with "category" |
| N | Image link (hide this column) | same pattern with "images/0" |
| A | Photo | =IF(N2="", "", IMAGE(N2)) |
| E | Options | =IFERROR(REGEXREPLACE(TEXTJOIN(", ", TRUE, FILTER(scrape!$A2:$ZZ2, REGEXMATCH(scrape!$A$1:$ZZ$1, "^variants/\d+/title$"))), "^Default Title$", ""), "") |
| F | In stock | =IFERROR(IF(INDEX(scrape!$A2:$ZZ2, MATCH("inStock", scrape!$A$1:$ZZ$1, 0))&""="", "Check", IF(UPPER(INDEX(scrape!$A2:$ZZ2, MATCH("inStock", scrape!$A$1:$ZZ$1, 0))&"")="TRUE", "Yes", "No")), "Check") |
| G | RRP | =IF(B2="", "", LET(p, N(IFERROR(INDEX(scrape!$A2:$ZZ2, MATCH("price", scrape!$A$1:$ZZ$1, 0)))), c, N(IFERROR(INDEX(scrape!$A2:$ZZ2, MATCH("compareAtPrice", scrape!$A$1:$ZZ$1, 0)))), MAX(p, c))) |
| H | Wholesale ex VAT | =IF(N(G2)=0, "", ROUND(G2 / (1 + settings!$B$2) * settings!$B$1, 2)) |
| I | Retailer margin | =IF(H2="", "", 1 - H2 / (G2 / (1 + settings!$B$2))) (format as %) |
| J | Case pack | =settings!$B$3, then type over it for products sold in other packs |
| K | Order qty | left empty for the shop buyer |
| L | Line total | =IF(N(K2)=0, "", IF(MOD(K2, J2)<>0, "Order in multiples of "&J2, K2 * H2)) |
| M | Offer wholesale? | you type Y or N |
Notes on the formulas:
- Photo: Google Sheets'
IMAGEfunction needs a full web address starting withhttpand does not accept images hosted on drive.google.com or SVG files. Shop image links from Shopify and WooCommerce are normally ordinary https links. - Options: Shopify calls the only variant of a single-variant product "Default Title"; the formula blanks that. WooCommerce rows stay empty here, so type sizes or colours by hand if you need them.
- RRP: the larger of price and compare-at price, so sale prices are ignored. If you set a compare-at price that is not your real normal price, fix it in your shop first.
- Prices with an admin export: for Shopify use "Variant Price" and "Variant Compare At Price"; for WooCommerce use "Regular price".
Under the table, add the order summary:
Order total ex VAT: =SUM(L2:L) Minimum first order: =IF(SUM(L2:L) >= settings!B4, "Met", "Add "&TEXT(settings!B4 - SUM(L2:L), "0.00")&" more")
SUM skips the "Order in multiples of" text, so a line with a wrong quantity is not counted until it is fixed.
Step 4: send it
- Add a filter (Data → Create a filter) and untick N in column M and No in column F, so only products you offer and have in stock show. Hide columns M and N.
- Put your brand name, wholesale contact email, payment terms and delivery terms in the rows above the header (insert rows at the top first).
- File → Download → PDF. Check the print preview: set the layout to landscape and "Fit to width", and confirm only the filtered rows and the photos appear.
- Send the PDF to shop buyers, or share a copy of the sheet with "Make a copy" access so they fill in column K themselves.
- Before each new season, re-import the scrape tab: prices, stock and new products update and your settings stay.
Partner programme opening soon
Partner programme opening soon: join the free waitlist. Planned terms are 50% of each referred sale (75% once you have 5+ paying customers), single level, paid through Gumroad only from revenue received.
Sources
- Product data scraper inputs and outputs (
startUrls,maxProductsPerShopdefault 100,includeDescription,SHOPS_SUMMARYstatuses, Shopify price, compare-at price and SKU from the cheapest variant, product type as category, WooCommerce regular price and categories, skipped shops not charged): Apify Store page (Actor input schema, README and source read 21 Oct 2026) - Google Sheets
IMAGEfunction: Google Docs Editors Help (read 21 Oct 2026). - VAT rates and how to quote business prices: check your own tax authority. 20% is the UK standard VAT rate; other countries differ.
Related
- Brand stockist price and stock check sheet
- Google Shopping product listing check sheet
- Export Shopify store products to CSV
- Export WooCommerce store products to CSV
Unadhi Guides are free, independent explainers. We correct errors as soon as we find them: write to mininglife7@gmail.com.