mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-19 00:59:40 +03:00
feat(web-test): add readSpreadsheet() for extracting report data
Reads 1C SpreadsheetDocument (report output) rendered in iframes.
Collects cells from div[x]/div[y] elements across all frames,
returns { rows: string[][], total }.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -107,6 +107,7 @@ In `exec` sandbox, all browser.mjs functions are available as globals — no `im
|
|||||||
|----------|-------------|
|
|----------|-------------|
|
||||||
| `getFormState()` | Current form: fields (with `required` flag for unfilled mandatory fields), buttons, tabs, table meta (columns + rowCount), filters |
|
| `getFormState()` | Current form: fields (with `required` flag for unfilled mandatory fields), buttons, tabs, table meta (columns + rowCount), filters |
|
||||||
| `readTable({maxRows, offset})` | Table row data: `{ columns, rows: [{col: val}], total }`. Use this to read grid contents |
|
| `readTable({maxRows, offset})` | Table row data: `{ columns, rows: [{col: val}], total }`. Use this to read grid contents |
|
||||||
|
| `readSpreadsheet()` | Read report output (SpreadsheetDocument): `{ rows: string[][], total }`. Use after clicking "Сформировать" |
|
||||||
| `getSections()` | Sections + commands of active section |
|
| `getSections()` | Sections + commands of active section |
|
||||||
| `getPageState()` | Sections + open tabs |
|
| `getPageState()` | Sections + open tabs |
|
||||||
| `getCommands()` | Commands of current section |
|
| `getCommands()` | Commands of current section |
|
||||||
|
|||||||
@@ -427,6 +427,63 @@ export async function readTable({ maxRows = 20, offset = 0 } = {}) {
|
|||||||
return await page.evaluate(readTableScript(formNum, { maxRows, offset }));
|
return await page.evaluate(readTableScript(formNum, { maxRows, offset }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read report output (SpreadsheetDocumentField) rendered in iframes.
|
||||||
|
* 1C renders spreadsheet documents as absolutely-positioned div cells inside iframes.
|
||||||
|
* Each cell is a div[x] inside a row div[y], text content in <span>.
|
||||||
|
* Returns { headers: string[][], data: string[][] } — arrays of cell arrays.
|
||||||
|
*/
|
||||||
|
export async function readSpreadsheet() {
|
||||||
|
ensureConnected();
|
||||||
|
const frames = page.frames();
|
||||||
|
const allCells = new Map();
|
||||||
|
|
||||||
|
for (let fi = 1; fi < frames.length; fi++) {
|
||||||
|
try {
|
||||||
|
const cells = await frames[fi].evaluate(`(() => {
|
||||||
|
const cells = [];
|
||||||
|
document.querySelectorAll('div[x]').forEach(d => {
|
||||||
|
const span = d.querySelector('span');
|
||||||
|
const text = span?.textContent?.trim() || '';
|
||||||
|
if (!text) return;
|
||||||
|
const rowDiv = d.parentElement;
|
||||||
|
const row = rowDiv?.getAttribute('y') || rowDiv?.className?.match(/R(\\d+)/)?.[1] || null;
|
||||||
|
const col = d.getAttribute('x');
|
||||||
|
if (row != null && col != null) cells.push({ r: parseInt(row), c: parseInt(col), t: text });
|
||||||
|
});
|
||||||
|
return cells;
|
||||||
|
})()`);
|
||||||
|
for (const cell of cells) {
|
||||||
|
const key = `${cell.r}_${cell.c}`;
|
||||||
|
if (!allCells.has(key) || cell.t.length > allCells.get(key).t.length) {
|
||||||
|
allCells.set(key, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch { /* skip inaccessible frames */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allCells.size === 0) return { error: 'no_spreadsheet', hint: 'No SpreadsheetDocument found. Report may not be generated yet.' };
|
||||||
|
|
||||||
|
// Group by row, determine max columns
|
||||||
|
const rowMap = new Map();
|
||||||
|
let maxCol = 0;
|
||||||
|
for (const cell of allCells.values()) {
|
||||||
|
if (!rowMap.has(cell.r)) rowMap.set(cell.r, new Map());
|
||||||
|
rowMap.get(cell.r).set(cell.c, cell.t);
|
||||||
|
if (cell.c > maxCol) maxCol = cell.c;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortedRows = [...rowMap.keys()].sort((a, b) => a - b);
|
||||||
|
const rows = sortedRows.map(r => {
|
||||||
|
const colMap = rowMap.get(r);
|
||||||
|
const arr = [];
|
||||||
|
for (let c = 0; c <= maxCol; c++) arr.push(colMap.get(c) || '');
|
||||||
|
return arr;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { rows, total: rows.length };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pick a value from an opened selection form: search + dblclick matching row.
|
* Pick a value from an opened selection form: search + dblclick matching row.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user