The product name contains a comma, and a quick split(',') has moved its quantity into the wrong column. Let Papa Parse read the CSV structure before you build the HTML table. Keep item codes as strings; an identifier such as 0017 is not the number seventeen.
Use this fictional shipment extract to make the distinction visible:

Open the complete example · Download the full HTML source
code,description,quantity
0017,"Cable, blue",6
0021,Adapter,4
The intended result is two records, a literal 0017 code, one description containing a comma, and ten units. Those are separate checks. A table can look tidy while its columns are wrong.
Parse fields, then decide their types
Load the Papa Parse browser distribution before your application script. The configuration documentation describes header, dynamicTyping, and the returned data, errors, and metadata.
const result = Papa.parse(csvText, {
header: true,
dynamicTyping: false,
skipEmptyLines: 'greedy'
});
if (result.errors.length) {
throw new Error('Fix the reported CSV errors before review.');
}
With this configuration, the header names become object keys and values remain strings. Convert only the quantity field after checking it. Do not enable blanket numeric conversion merely to make the total easier to calculate.
Require the three expected headers, with no duplicates or extra columns. Papa Parse documents automatic renaming of duplicate headers; that prevents overwriting, but a renamed field is still a schema change your review should expose. Compare the returned fields with the agreed header list before rendering.
Reject a plausible but incomplete total
For this fixture, quantities must be whole, nonnegative decimal counts. Reject an empty value, a minus sign, or text such as 6 boxes. Do not use parseInt() as a validator: accepting the first numeric part would conceal the rest of that cell.
const quantities = result.data.map((row, index) => {
const value = row.quantity.trim();
if (!/^\d+$/.test(value)) {
throw new Error(`Check quantity on data row ${index + 1}.`);
}
const number = Number(value);
if (!Number.isSafeInteger(number)) throw new Error('Count too large.');
return number;
});
Check the sum is also a safe integer before showing it. A rejected row should leave the total unavailable, rather than quietly vanish from the calculation. Clear the old table and total as soon as the source text changes.
Put literal data into table cells
Create th and td elements, then assign each value through textContent. A description is data, even when it contains angle brackets. There is no reason to interpret a shipment label as page markup.
Place the column headings in thead, identify the table with a caption, and keep the quantity column right aligned. For layout details, the existing CSV-to-HTML table guide covers the reading surface. This recipe addresses the earlier step: parsing quoted fields and applying a deliberate schema.
Before replacing the fictional data, inspect both rows and the ten-unit total. Then introduce a missing quantity and an extra field to check that the page stops showing a successful review. Do not treat a visually complete table as proof that the source was accepted by another system.
Keep the original CSV for import or analysis. If the HTML review belongs in NOS, include that original alongside the readable result and ask the reviewer to confirm the codes and descriptions. The review page does not replace the receiving system's CSV requirements.