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:
@@ -4,17 +4,20 @@ import { useConfirm } from "../confirm";
|
|||||||
import Icon from "../components/Icon";
|
import Icon from "../components/Icon";
|
||||||
import { asTree } from "../categoryTree";
|
import { asTree } from "../categoryTree";
|
||||||
|
|
||||||
// Baut die Etiketten-CSV (Semikolon, BOM für Excel). QR-Inhalt = Link aufs Stück.
|
// Baut die Etiketten-CSV mit wählbarem Trennzeichen (BOM für Excel-Umlaute).
|
||||||
function buildLabelCsv(rows, origin) {
|
// QR-Inhalt = Link aufs Stück.
|
||||||
|
function buildLabelCsv(rows, origin, delim = ",") {
|
||||||
const head = ["QR-Inhalt", "UID", "Produkt", "Marke", "Kategorie", "Lagerort"];
|
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 esc = (v) => {
|
||||||
const s = String(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) {
|
for (const r of rows) {
|
||||||
lines.push([`${origin}/i/${r.uid}`, r.uid, r.product, r.brand, r.category, r.location]
|
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");
|
return "" + lines.join("\r\n");
|
||||||
}
|
}
|
||||||
@@ -32,9 +35,16 @@ export default function Transfer() {
|
|||||||
const [selCats, setSelCats] = useState(() => new Set());
|
const [selCats, setSelCats] = useState(() => new Set());
|
||||||
const [labelBusy, setLabelBusy] = useState(false);
|
const [labelBusy, setLabelBusy] = useState(false);
|
||||||
const [labelInfo, setLabelInfo] = useState(null);
|
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(() => {}); }, []);
|
useEffect(() => { api.listCategories().then(setCategories).catch(() => {}); }, []);
|
||||||
|
|
||||||
|
function changeDelim(v) {
|
||||||
|
setLabelDelim(v);
|
||||||
|
localStorage.setItem("label_delim", v);
|
||||||
|
}
|
||||||
|
|
||||||
function toggleCat(id, on) {
|
function toggleCat(id, on) {
|
||||||
setSelCats((prev) => {
|
setSelCats((prev) => {
|
||||||
const neu = new Set(prev);
|
const neu = new Set(prev);
|
||||||
@@ -50,7 +60,7 @@ export default function Transfer() {
|
|||||||
try {
|
try {
|
||||||
const rows = await api.labelRows([...selCats]);
|
const rows = await api.labelRows([...selCats]);
|
||||||
if (!rows.length) { setLabelInfo("Keine Einzelstücke in der Auswahl."); return; }
|
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 blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const a = document.createElement("a");
|
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
|
verknüpfen – sie erzeugt QR-Code und Text automatisch. Kategorien wählen
|
||||||
(Unterkategorien sind enthalten); ohne Auswahl kommen alle Einzelstücke.
|
(Unterkategorien sind enthalten); ohne Auswahl kommen alle Einzelstücke.
|
||||||
</p>
|
</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">
|
<div className="kat-check-liste">
|
||||||
{asTree(categories).filter((c) => c.tracking === "object").map((c) => (
|
{asTree(categories).filter((c) => c.tracking === "object").map((c) => (
|
||||||
<label key={c.id} className="check-inline" style={{ paddingLeft: c.depth * 18 }}>
|
<label key={c.id} className="check-inline" style={{ paddingLeft: c.depth * 18 }}>
|
||||||
|
|||||||
Reference in New Issue
Block a user