162 lines
4.8 KiB
TypeScript
162 lines
4.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { createHash } from "node:crypto";
|
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { dirname, resolve } from "node:path";
|
|
import ExcelJS from "exceljs";
|
|
import {
|
|
createDefaultExternalXlsxTransportConfiguration,
|
|
type ExternalXlsxScalar,
|
|
} from "../src/external-model/xlsx/external-xlsx-contracts.js";
|
|
import {
|
|
createExternalXlsxReturn,
|
|
parseExternalXlsx,
|
|
} from "../src/external-model/xlsx/external-xlsx-transport.js";
|
|
|
|
async function main() {
|
|
const inputPath = resolve(
|
|
process.argv[2] ?? "docs/spec/kbp-Stromkreis.xlsx"
|
|
);
|
|
const outputPath = resolve(
|
|
process.argv[3] ?? "data/revit-reference/kbp-Stromkreis-R2-Rueckgabe.xlsx"
|
|
);
|
|
assert.notEqual(
|
|
inputPath,
|
|
outputPath,
|
|
"Eingabe- und Ausgabedatei müssen verschieden sein."
|
|
);
|
|
|
|
const source = readFileSync(inputPath);
|
|
const configuration = createDefaultExternalXlsxTransportConfiguration();
|
|
const document = await parseExternalXlsx({
|
|
fileName: inputPath,
|
|
bytes: source,
|
|
configuration,
|
|
});
|
|
const objectRows = document.rows.filter((row) => row.classification === "object");
|
|
const suspectRows = document.rows.filter(
|
|
(row) => row.classification === "suspect-object"
|
|
);
|
|
const worksharingIdColumn = document.columns.find(
|
|
(column) => column.header === configuration.columns.worksharingId
|
|
)?.columnNumber;
|
|
assert.ok(worksharingIdColumn, "Worksharing-ID-Spalte wurde nicht aufgelöst.");
|
|
|
|
assert.equal(objectRows.length, 487, "Es werden 487 Objektzeilen erwartet.");
|
|
assert.equal(suspectRows.length, 0, "Es werden keine verdächtigen Zeilen erwartet.");
|
|
assert.equal(
|
|
document.columns.filter((column) => column.comment !== null).length,
|
|
14,
|
|
"Es werden 14 Kopfzeilenkommentare erwartet."
|
|
);
|
|
assert.equal(
|
|
document.issues.filter((issue) => issue.code === "duplicate-ifc-guid").length,
|
|
0,
|
|
"Die Musterdatei darf keine exakten IfcGUID-Duplikate enthalten."
|
|
);
|
|
|
|
const testValues = [
|
|
{
|
|
circuitCombined: "UV_R2_TEST-2F1",
|
|
electricalPowerW: 111,
|
|
voltageV: 230,
|
|
currentA: 0.48,
|
|
},
|
|
{
|
|
circuitCombined: "UV_R2_TEST-2F2",
|
|
electricalPowerW: 222,
|
|
voltageV: 230,
|
|
currentA: 0.97,
|
|
},
|
|
{
|
|
circuitCombined: "UV_R2_TEST-3F1",
|
|
electricalPowerW: 333,
|
|
voltageV: 400,
|
|
currentA: 0.48,
|
|
},
|
|
] satisfies Record<string, ExternalXlsxScalar>[];
|
|
|
|
const updates = testValues.map((values, index) => {
|
|
const value = objectRows[index]?.cells[worksharingIdColumn - 1]?.value;
|
|
if (typeof value !== "string") {
|
|
throw new Error("Worksharing-ID muss Text sein.");
|
|
}
|
|
return { worksharingId: value, values };
|
|
});
|
|
const result = await createExternalXlsxReturn({
|
|
fileName: inputPath,
|
|
bytes: source,
|
|
configuration,
|
|
updates,
|
|
});
|
|
assert.equal(result.exportedObjectCount, 487);
|
|
mkdirSync(dirname(outputPath), { recursive: true });
|
|
writeFileSync(outputPath, result.bytes);
|
|
|
|
const outputDocument = await parseExternalXlsx({
|
|
fileName: outputPath,
|
|
bytes: result.bytes,
|
|
configuration,
|
|
});
|
|
assert.equal(
|
|
outputDocument.rows.filter((row) => row.classification === "object").length,
|
|
487
|
|
);
|
|
assert.equal(
|
|
outputDocument.rows.some((row) => row.classification !== "object"),
|
|
false,
|
|
"Die Rückgabedatei darf keine Summen- oder Hinweiszeilen enthalten."
|
|
);
|
|
assert.equal(outputDocument.sheetName, document.sheetName);
|
|
assert.deepEqual(
|
|
outputDocument.columns,
|
|
document.columns,
|
|
"Kopfzeilen, Kommentare und Spaltenbreiten müssen erhalten bleiben."
|
|
);
|
|
assert.deepEqual(
|
|
outputDocument.rows.slice(updates.length).map((row) => row.cells),
|
|
objectRows.slice(updates.length).map((row) => row.cells),
|
|
"Nicht geänderte Objektzellen müssen Wert, Typ und Zahlenformat behalten."
|
|
);
|
|
const outputWorkbook = new ExcelJS.Workbook();
|
|
await outputWorkbook.xlsx.load(result.bytes as never);
|
|
const commentedCells: string[] = [];
|
|
outputWorkbook.worksheets[0].eachRow({ includeEmpty: true }, (row) => {
|
|
row.eachCell({ includeEmpty: true }, (cell) => {
|
|
if (cell.note !== undefined) commentedCells.push(cell.address);
|
|
});
|
|
});
|
|
assert.equal(
|
|
commentedCells.length,
|
|
14,
|
|
"Nur die 14 Kopfzellen dürfen Kommentare enthalten."
|
|
);
|
|
assert.equal(
|
|
commentedCells.every((address) => address.endsWith("1")),
|
|
true,
|
|
"Datenzellen dürfen keine Kommentare enthalten."
|
|
);
|
|
|
|
process.stdout.write(
|
|
`${JSON.stringify(
|
|
{
|
|
input: inputPath,
|
|
output: outputPath,
|
|
inputBytes: source.length,
|
|
outputBytes: result.bytes.length,
|
|
inputSha256: createHash("sha256").update(source).digest("hex"),
|
|
outputSha256: createHash("sha256").update(result.bytes).digest("hex"),
|
|
sheetName: document.sheetName,
|
|
objectCount: objectRows.length,
|
|
headerCommentCount: document.columns.filter(
|
|
(column) => column.comment !== null
|
|
).length,
|
|
exactDuplicateIfcGuidCount: 0,
|
|
changedObjectCount: updates.length,
|
|
},
|
|
null,
|
|
2
|
|
)}\n`
|
|
);
|
|
}
|
|
|
|
void main();
|