feat(parse): report per-sheet recognition and block error sheets
- parseWorkbook returns a report per sheet (table counts, issues, ok) - sheets with E-level issues cannot be selected (spec section 2.3) - pier input carries its source sheet name Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
35d89dc4e2
commit
01d2bf4958
8 files changed
+122
-16
No files matched your search
@@ -5,24 +5,50 @@ import type { Bearing, FoundationType, Issue, IpPoint, PierInput, PierType, Row
|
||||
type Cell = string | number | null | undefined;
|
||||
type Grid = Cell[][];
|
||||
|
||||
export interface SheetReport {
|
||||
name: string;
|
||||
/** Pier input tables found (교각 정보 표 개수). */
|
||||
tables: { pier: number; ip: number; bearing: number };
|
||||
piers: number;
|
||||
issues: Issue[];
|
||||
/** A sheet with any E-level issue cannot be selected (spec §2.3). */
|
||||
ok: boolean;
|
||||
}
|
||||
|
||||
export interface ParseResult {
|
||||
piers: PierInput[];
|
||||
issues: Issue[];
|
||||
sheets: SheetReport[];
|
||||
}
|
||||
|
||||
const PIER_TYPES: PierType[] = ['T형', '2주형', '3주형'];
|
||||
const FOUNDATION_TYPES: FoundationType[] = ['말뚝기초', '직접기초', '현장타설말뚝'];
|
||||
|
||||
/** Reads every sheet and collects the pier tables found by their header strings (position-independent). */
|
||||
/** Reads every sheet, finds the pier tables by their header strings, and reports each sheet separately. */
|
||||
export function parseWorkbook(wb: XLSX.WorkBook): ParseResult {
|
||||
const piers: PierInput[] = [];
|
||||
const issues: Issue[] = [];
|
||||
const sheets: SheetReport[] = [];
|
||||
for (const sheetName of wb.SheetNames) {
|
||||
const ws = wb.Sheets[sheetName];
|
||||
const grid = XLSX.utils.sheet_to_json<Cell[]>(ws, { header: 1, raw: true, defval: null }) as Grid;
|
||||
piers.push(...parseSheet(grid, sheetName, issues));
|
||||
const sheetIssues: Issue[] = [];
|
||||
const found = parseSheet(grid, sheetName, sheetIssues);
|
||||
piers.push(...found);
|
||||
issues.push(...sheetIssues);
|
||||
sheets.push({
|
||||
name: sheetName,
|
||||
tables: {
|
||||
pier: findHeaders(grid, (r) => r[0] === '교각명' && r[1] === '교각형식').length,
|
||||
ip: findHeaders(grid, (r) => r[0] === '교각명' && r[1] === 'IP점').length,
|
||||
bearing: findHeaders(grid, (r) => r[0] === '교각명' && r[1] === '받침번호').length,
|
||||
},
|
||||
piers: found.length,
|
||||
issues: sheetIssues,
|
||||
ok: found.length > 0 && !sheetIssues.some((i) => i.level === 'E'),
|
||||
});
|
||||
}
|
||||
return { piers, issues };
|
||||
return { piers, issues, sheets };
|
||||
}
|
||||
|
||||
function parseSheet(grid: Grid, sheet: string, issues: Issue[]): PierInput[] {
|
||||
@@ -61,18 +87,19 @@ function parseSheet(grid: Grid, sheet: string, issues: Issue[]): PierInput[] {
|
||||
code: 'E03',
|
||||
level: 'E',
|
||||
pier: name,
|
||||
message: `${sheet} ${bad.row}행: 방위각 문자열을 읽을 수 없습니다. 예: 75°56'55.9"`,
|
||||
message: `${bad.row}행: 방위각을 읽을 수 없습니다. 예: 75°56'55.9" 형식으로 고치세요.`,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const type = String(cells[1]) as PierType;
|
||||
const foundation = String(cells[5]) as FoundationType;
|
||||
if (!PIER_TYPES.includes(type) || !FOUNDATION_TYPES.includes(foundation)) {
|
||||
issues.push({ code: 'E01', level: 'E', pier: name, message: `${sheet} ${index + 1}행: 교각형식 또는 기초 형식을 알 수 없습니다.` });
|
||||
issues.push({ code: 'E01', level: 'E', pier: name, message: `${index + 1}행: 교각형식 또는 기초 형식을 알 수 없습니다.` });
|
||||
continue;
|
||||
}
|
||||
piers.push({
|
||||
name,
|
||||
sheet,
|
||||
type,
|
||||
copingTopEl: Number(cells[2]),
|
||||
footingBottomEl: Number(cells[3]),
|
||||
|
||||
Reference in new issue
Block a user