Etiketten-Export: Trennzeichen waehlbar (Komma/Semikolon/Tab), gemerkt

P-touch will Komma, wir hatten fest Semikolon - jetzt einstellbar und in
localStorage gemerkt, sodass man es nur einmal setzt. Standard ist Komma.
Anfuehrungszeichen werden passend zum gewaehlten Trennzeichen gesetzt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-26 09:54:35 +02:00
parent 2ebdf94b16
commit b4b203a117

View File

@@ -4,17 +4,20 @@ import { useConfirm } from "../confirm";
import Icon from "../components/Icon";
import { asTree } from "../categoryTree";
// Baut die Etiketten-CSV (Semikolon, BOM für Excel). QR-Inhalt = Link aufs Stück.
function buildLabelCsv(rows, origin) {
// Baut die Etiketten-CSV mit wählbarem Trennzeichen (BOM für Excel-Umlaute).
// QR-Inhalt = Link aufs Stück.
function buildLabelCsv(rows, origin, delim = ",") {
const head = ["QR-Inhalt", "UID", "Produkt", "Marke", "Kategorie", "Lagerort"];
const delimRe = delim === "\t" ? "\\t" : delim;
const needsQuote = new RegExp(`[${delimRe}"\\n\\r]`);
const esc = (v) => {
const s = String(v ?? "");
return /[";\n\r]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
return needsQuote.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
};
const lines = [head.join(";")];
const lines = [head.map(esc).join(delim)];
for (const r of rows) {
lines.push([`${origin}/i/${r.uid}`, r.uid, r.product, r.brand, r.category, r.location]
.map(esc).join(";"));
.map(esc).join(delim));
}
return "" + lines.join("\r\n");
}
@@ -32,9 +35,16 @@ export default function Transfer() {
const [selCats, setSelCats] = useState(() => new Set());
const [labelBusy, setLabelBusy] = useState(false);
const [labelInfo, setLabelInfo] = useState(null);
// Gemerktes Trennzeichen (Standard Komma P-touch mag das lieber).
const [labelDelim, setLabelDelim] = useState(() => localStorage.getItem("label_delim") || ",");
useEffect(() => { api.listCategories().then(setCategories).catch(() => {}); }, []);
function changeDelim(v) {
setLabelDelim(v);
localStorage.setItem("label_delim", v);
}
function toggleCat(id, on) {
setSelCats((prev) => {
const neu = new Set(prev);
@@ -50,7 +60,7 @@ export default function Transfer() {
try {
const rows = await api.labelRows([...selCats]);
if (!rows.length) { setLabelInfo("Keine Einzelstücke in der Auswahl."); return; }
const csv = buildLabelCsv(rows, window.location.origin);
const csv = buildLabelCsv(rows, window.location.origin, labelDelim);
const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
@@ -206,6 +216,14 @@ export default function Transfer() {
verknüpfen sie erzeugt QR-Code und Text automatisch. Kategorien wählen
(Unterkategorien sind enthalten); ohne Auswahl kommen alle Einzelstücke.
</p>
<label style={{ maxWidth: 340 }}>
Trennzeichen (für die Etiketten-Software)
<select value={labelDelim} onChange={(e) => changeDelim(e.target.value)}>
<option value=",">Komma ( , ) z.B. P-touch</option>
<option value=";">Semikolon ( ; ) z.B. Excel (Deutsch)</option>
<option value={"\t"}>Tabulator</option>
</select>
</label>
<div className="kat-check-liste">
{asTree(categories).filter((c) => c.tracking === "object").map((c) => (
<label key={c.id} className="check-inline" style={{ paddingLeft: c.depth * 18 }}>