CSV row count doesn't match? Count records, not text lines
A supplier says an export contains two records, but your text editor shows four lines. Before deleting blank-looking lines or merging cells, check whether a quoted field contains a line break. You may be counting two different things.
Why the counts differ
A CSV record can span more than one physical line. The header is also a record, although it is usually excluded from the number of data rows. For the synthetic file below, all three of these counts are correct:
- Physical text lines: 4.
- Parsed records, including the header: 3.
- Data records, excluding the header: 2.
The example follows comma-separated fields with double-quote escaping. Quoted fields can contain line breaks, commas and escaped quotes. RFC 4180
Reproduce the mismatch with a small file
Download 03-multiline.csv. This is synthetic UTF-8 data with CRLF line endings. Its memo values contain Korean text; the counting rules do not depend on the language. Keep the original file unchanged.
id,memo
A1,"첫 줄
둘째 줄"
A2,"쉼표, 따옴표 ""예"""
The memo for A1 occupies two physical lines but belongs to one field in one record. The comma and escaped quotes in A2 are content, too. A comma is not always a column boundary.
Check it in CSV Helper before changing anything
Open the CSV checker and select the sample.
1. Check the detected values shown next to the selectors. If a selector is set to Auto, distinguish that setting from the detected result. 2. For this file, verify UTF-8, comma delimiter and the first-record-as-header setting. 3. Compare physical lines, records including the header and data records. Expect 4 / 3 / 2, with 2 fields per record. 4. Inspect the memo preview. A1's line break and A2's punctuation should still be present.
This is a check of how the file is read. It does not remove embedded line breaks or rewrite the original. Keep a separate copy if another application needs a different format.
Developer check: use a CSV parser
Save the downloaded file beside your working script and run this with Python 3:
import csv
from pathlib import Path
path = Path('03-multiline.csv')
text = path.read_bytes().decode('utf-8')
with path.open(encoding='utf-8', newline='') as f:
rows = list(csv.reader(f, strict=True))
print(len(text.splitlines()), len(rows), len(rows) - 1)
print([len(row) for row in rows])
Expected output:
4 3 2
[2, 2, 2]
newline='' lets the CSV reader handle newline sequences. Splitting the text into lines first would break the multiline field. split(',') is also unsuitable for fields containing quoted commas. Python csv documentation
The existing 03-normalized.csv was written with a CSV writer and parsed again to verify that every cell value was preserved. Normalizing CSV syntax is different from deleting newlines inside a memo.
When this explanation is not enough
A row-count mismatch alone does not prove that the file is complete. Confirm that you are comparing the same export, filters, header setting and empty-record rules.
The unclosed-quote sample is intentionally malformed. Python's strict reader rejects it; do not present a partial parse as a confirmed total. Strict parsing does not check every business rule or guarantee equal field counts, so check record widths separately.
Editor soft wrapping is not a physical newline. A final newline is not automatically an extra data record. Blank records, missing fields, parser settings and spreadsheet loading limits can cause other disagreements. This small example is not a large-file performance test.
Before sending the count to a colleague
Write “2 data records, header excluded”, rather than just “2 rows.” Include the delimiter and any filtering rules when those matter. If the file is malformed, report the error instead of a definitive record count.
Reviewed: 2026-10-18. Synthetic fixtures and Python execution verified; no Excel GUI or browser-interface test was performed. Existing Korean guide and fixture verification are reused.
AI assistance: AI helped draft this guide and its example code. The code was executed against synthetic files and checked against the stated results. No customer data was used.