fix: 清空区域兼容 cellPos 与 startRow/startColumn 键并支持清除格式模式
This commit is contained in:
parent
753508b500
commit
0fe264a884
@ -1,6 +1,7 @@
|
||||
import { readFile, mkdtemp, rm } from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import type { Catalog, CatalogComponent, FlowNode } from "../../shared/types";
|
||||
import type { RunContext } from "../engine/types";
|
||||
@ -19,7 +20,7 @@ afterEach(async () => Promise.all(dirs.splice(0).map((dir) => rm(dir, { recursiv
|
||||
|
||||
describe("common Excel aliases", () => {
|
||||
it("registers only real catalog aliases", async () => {
|
||||
const catalog = JSON.parse(await readFile("resources/catalog.json", "utf8")) as Catalog;
|
||||
const catalog = JSON.parse(await readFile(path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../../resources/catalog.json"), "utf8")) as Catalog;
|
||||
const ids = new Set(catalog.components.map((item) => item.id));
|
||||
expect(EXCEL_COMMON_ALIASES.length).toBeGreaterThanOrEqual(25);
|
||||
for (const id of EXCEL_COMMON_ALIASES) { expect(ids.has(id), id).toBe(true); expect(getHandler(id), id).toBeTruthy(); }
|
||||
@ -82,4 +83,23 @@ describe("common Excel aliases", () => {
|
||||
const savedAs = await run("Excel_SaveAs", { objExcel: created, filename: "rel-target.xlsx", isAbsolutePath: "False" }) as { path: string };
|
||||
expect(savedAs.path).toBe(path.resolve(directory, "rel-target.xlsx"));
|
||||
});
|
||||
|
||||
it("clears a range through the Excel_ClearRange cellPos key", async () => {
|
||||
const directory = await mkdtemp(path.join(os.tmpdir(), "rpa-excel-clear-")); dirs.push(directory);
|
||||
const created = await run("Excel_NewExcel", { filePath: directory, name: "clear.xlsx" }) as { path: string };
|
||||
await run("Excel_WriteRange", { objExcel: created, sheet: "Sheet1", cellPos: "A1", data: [["甲", "乙"], ["丙", "丁"]] });
|
||||
await run("Excel_ClearRange", { objExcel: created, sheet: "Sheet1", cellPos: "A1:B2", isFormat: "False", isSave: "True" });
|
||||
const reopened = await run("Excel_OpenExcel", { filePath: created.path }) as { id: string };
|
||||
await expect(run("Excel_Cs_ReadContentV2", { workbook: reopened, sheet: "Sheet1", excelRng: "A1:B2" })).resolves.toEqual([["", ""], ["", ""]]);
|
||||
});
|
||||
|
||||
it("clears through the Excel_Cs_ClearRange startRow/startColumn keys", async () => {
|
||||
const directory = await mkdtemp(path.join(os.tmpdir(), "rpa-excel-clear-cs-")); dirs.push(directory);
|
||||
const created = await run("Excel_NewExcel", { filePath: directory, name: "clear-cs.xlsx" }) as { path: string };
|
||||
await run("Excel_WriteRange", { objExcel: created, sheet: "Sheet1", cellPos: "A1", data: [["1", "2"], ["3", "4"]] });
|
||||
await run("Excel_Cs_ClearRange", { objExcel: created, sheet: "Sheet1", startRow: "2", startColumn: "A", lastRow: "2", lastColumn: "B", mode: "内容", save: "True" });
|
||||
const reopened = await run("Excel_OpenExcel", { filePath: created.path }) as { id: string };
|
||||
await expect(run("Excel_Cs_ReadContentV2", { workbook: reopened, sheet: "Sheet1", excelRng: "A2:B2" })).resolves.toEqual([["", ""]]);
|
||||
await expect(run("Excel_Cs_ReadContentV2", { workbook: reopened, sheet: "Sheet1", excelRng: "A1:B1" })).resolves.toEqual([["1", "2"]]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -164,12 +164,30 @@ register("Excel_Cs_DeleteColumn", async (_ctx, node, args) => {
|
||||
register("Excel_Cs_ClearRangeV4", async (_ctx, node, args) => {
|
||||
const source = await loadWorkbook(args, node.id, node.componentId);
|
||||
const sheet = worksheetOf(source.workbook, args);
|
||||
const range = text(args, ["excelRng", "range"]);
|
||||
// 兼容各别名版本的键:V4=excelRng、V2/V3=range、Legacy Excel_ClearRange=cellPos、V1=startRow/startColumn/lastRow/lastColumn
|
||||
let range = text(args, ["excelRng", "range", "cellPos"]);
|
||||
if (!range) {
|
||||
const startRow = text(args, ["startRow"]);
|
||||
const startColumn = text(args, ["startColumn"]);
|
||||
if (startRow && startColumn) {
|
||||
const lastRow = text(args, ["lastRow"], startRow);
|
||||
const lastColumn = text(args, ["lastColumn"], startColumn);
|
||||
range = `${startColumn}${startRow}:${lastColumn}${lastRow}`;
|
||||
}
|
||||
}
|
||||
if (!range) throw new RuntimeError("validation_error", "Range is empty", { nodeId: node.id, componentId: node.componentId });
|
||||
const [start, end = start] = range.split(":");
|
||||
const first = sheet.getCell(start);
|
||||
const last = sheet.getCell(end);
|
||||
for (let row = first.row; row <= last.row; row += 1) for (let column = first.col; column <= last.col; column += 1) sheet.getCell(row, column).value = null;
|
||||
// 清除模式:全部=内容+格式,格式=仅格式,其余(内容/默认)=仅内容;Legacy isFormat=True 同样清格式
|
||||
const mode = text(args, ["clearType", "mode"], "内容");
|
||||
const clearFormat = mode.includes("全部") || mode.includes("格式") || truthy(value(args, ["isFormat"]));
|
||||
const clearValue = !mode.includes("格式");
|
||||
for (let row = first.row; row <= last.row; row += 1) for (let column = first.col; column <= last.col; column += 1) {
|
||||
const cell = sheet.getCell(row, column);
|
||||
if (clearValue) cell.value = null;
|
||||
if (clearFormat) cell.style = {};
|
||||
}
|
||||
await saveWhenRequested(source, args);
|
||||
return range;
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user