Back to blog

· By Sajeevan (Saj) Veeriah

Engineering software · 4 min read

The hard part of a CSV import is deciding what may change

Preserving identifiers, resolving ambiguity and making an import reviewable before it changes an operational system.

Fictional import review: code 00127 retains its leading zeros; an approved change moves AUD 10.00 to AUD 13.00. Duplicate code 00418 is held. These are illustrative rows, not client data.
Fictional import review: code 00127 retains its leading zeros; an approved change moves AUD 10.00 to AUD 13.00. Duplicate code 00418 is held. These are illustrative rows, not client data. View full-size diagram

A CSV import can finish successfully and still damage the meaning of the data. An item code loses its leading zeros. A blank price becomes zero. Two similar descriptions are treated as the same product.

The public record for my pricing and inventory project describes operator-reviewed imports and explicit matching rules. This article develops the general engineering questions behind that approach, using invented product records and prices. No client data or private implementation is included.

Define the file contract before the parser

RFC 4180 documents a common CSV format, including quoting fields that contain commas, line breaks or quotes. It is an informational RFC, and actual importers may impose their own rules. Record the destination's required headers, ordering, encoding and accepted values rather than assuming that any file labelled CSV is interchangeable.

Keep a distinction between a syntactically valid row and a valid business change. A parser can accept a negative quantity perfectly well. Whether that value is allowed depends on the field and the workflow.

Use a fixture containing an embedded comma, an embedded quote and a multiline description. Check the parsed field values and the exported round trip. Counting separators is not enough to validate a CSV parser.

Sources: [1]

Treat identifiers as identifiers

In a fictional catalogue, item 00127 is a string. Converting it to the number 127 discards information that may be required by another system. The same concern applies to barcodes and supplier references even when they contain only digits.

Define normalisation narrowly. Removing accidental outer whitespace may be appropriate; dropping punctuation or case may merge records that the source treats as distinct. Show the original and normalised values during review when that transformation affects matching.

When two rows normalise to the same code, surface the collision. Choosing the first row silently makes file order a business rule. A reviewer needs to know that a decision exists.

Make ambiguity visible

A useful matching sequence is exact approved identifier, then a maintained alias, then a suggestion requiring review. Similar descriptions can help a person investigate a mismatch; they are weak authority for overwriting an operational record.

The proposed review below keeps unresolved rows out of the approved change set. A missing supplier row is not automatically a request to delete an existing item.

Make ambiguity visible
Incoming rowProposed handling
Unique exact code; valid fieldsPrepare a before-and-after comparison.
Known alias with an approved mappingShow the alias used and the target record.
Similar description; different codeRequire review; do not silently update.
Duplicate code or missing required priceHold the row with a specific reason.
Existing item absent from the fileLeave unchanged unless a separate deletion rule is authorised.

Sources: [2]

Make numeric rules explicit

SQLite's documentation explains that binary floating-point values are approximate. For monetary processing that requires exact decimal behaviour, choose an appropriate decimal representation or an integer representation with an explicit scale. Validate range and precision as part of that choice.

For an invented arithmetic example, AUD 10.00 with a 30% markup becomes AUD 13.00 before any separately specified tax treatment. A 30% margin calculation would instead divide the cost by 0.70, producing approximately AUD 14.2857 before rounding. Confusing the two rules changes the result far more than a display-format issue.

Specify when rounding occurs and how ties are handled. If supplier costs contain fractions of a cent, an integer-cents model alone may discard required precision. Keep this rule in the domain logic and test it independently of the screen.

Sources: [3]

A useful import has a before and an after

Before export, show changed, unchanged and held rows separately. Include the old value, proposed value and reason for the match. Give the reviewer a manageable set of decisions rather than a green button beside a large unexplained row count.

Test a second application of the same intended change. It should not create duplicate records or compound a markup. Also test a stale target catalogue: if another person changed the target after the comparison, require a fresh comparison or a defined conflict resolution.

A recovery export can help restore previous values, but its scope needs care. It should not overwrite legitimate edits made after the import. The useful acceptance question is whether an operator can explain each change and recover from a mistaken run without guessing.

Sources and further reading

Sources checked on 11 September 2026. Catalogue rows and AUD amounts are invented teaching examples; this is software design guidance, not a pricing recommendation.

  1. RFC 4180: Common Format and MIME Type for CSV Files, October 2005, Informational
  2. Portfolio project: SWL Pricing and Inventory Control, public matching and review boundary
  3. SQLite: Floating Point Numbers; live documentation
Back to all posts