自动化脚本
自动化脚本是一段 JavaScript,它可以在不打开应用窗口的情况下打开、修改和保存图纸:例如,为每个订单生成图纸的订单或数据库系统、将一个文件夹的图纸转换为 DXF 文件的批处理作业,或者每晚向切割台导出文件。它使用与扩展相同的绘图 API,并增加了打开和保存图纸、运行库中的参数化设计、导出图纸以及读写文件的函数。
// orders.js: a box for each order, as a PDF for the customer and a DXF for the sample table
const box = runDesign("Packaging › FEFCO 0201 Regular slotted container", { L: 400, W: 300, D: 250 });
box.setNote("order", args[0]);
box.export("pdf", "out/" + args[0] + ".pdf");
box.export("dxf", "out/" + args[0] + ".dxf");
box.save("out/" + args[0] + ".piq");
log(args[0], "blank", box.info().totals.width, "×", box.info().totals.height);
运行脚本
从命令行运行,使用应用的程序和 run 一词:
PiQ run orders.js A-1017
PiQ run --folder D:\Orders --timeout 120 orders.js A-1017
选项放在脚本之前;脚本之后的每个词都作为 args 传给脚本(args[0] 为 "A-1017")。脚本记录的内容写入输出,失败原因写入错误输出。运行到结束时退出代码为 0,失败时为 1,命令行有误时为 2——这样运行它的系统就能判断结果。不会打开任何窗口。
| 选项 | 含义 |
|---|---|
--folder DIR |
脚本可以读写的文件夹及其中的文件夹;需要多个时可多次给出。第一个是其工作文件夹:不完整的路径从这里读取。未给出时,为当前文件夹和脚本自身所在的文件夹。 |
--extensions DIR |
一个 Extensions 文件夹,脚本使用其中的库设计(Parametric)、后处理器、报表、保存扩展和机器配置文件(Profiles);未给出时,使用您的和应用自带的。 |
--allow-host HOST |
可以从中打开图纸的 Web 主机(example.com,或 *.example.com 表示其下的主机)。除非给出,否则没有。 |
--timeout SECONDS |
最长运行时间:除非给出,否则为 600 秒。 |
--no-save-extensions |
保存图纸时不运行保存扩展。 |
--help |
显示以上所有说明。 |
从应用中运行:文件 › 扩展 › 运行脚本… 会询问脚本及其参数(以空格分隔,含空格的参数用双引号括起来),并在后台运行。脚本可以使用其所在文件夹及其子文件夹中的文件。它记录的内容显示在当前打开图纸的交互窗口中,结束时会说明运行情况。show(drawing) 会在应用中打开它生成的图纸,以便查看或继续处理。请将脚本放在您存放其所处理文件的位置;应用在其 Extensions\Automation 文件夹中自带一个示例。
与在应用中一样,保存和导出需要可用的许可证:没有许可证时,脚本可以打开和读取图纸,而 save 和 export 会失败并说明原因。
图纸
| 函数 | 含义 |
|---|---|
openDrawing(path, values) |
打开一个图纸文件。values(如果给出)在读取时取代文件中其变量自身的值,与运行参数化相同:openDrawing("tray.piq", { L: 300, BOARD: "B flute" })。 |
openDrawing(url, values) |
从 Web 上允许的主机(--allow-host)打开图纸。 |
openDrawing(text, values) |
图纸文本(图纸语言,其中含有换行符):由其生成的图纸。 |
openDrawing({path, url, text, values, units, name}) |
同上,完整写法:units 为 "mm" 或 "in"(否则按文件的规定),name 为其名称。 |
newDrawing({units, industry, name}) |
一张新的空白图纸:使用 "mm"(除非另行指定),如果指定了行业("Packaging"、"SheetMetal"……),则属于该行业。 |
runDesign(name, values) |
用给定值运行库中的设计,与 文件 › 运行参数化 的运行方式相同,行业为其所在文件夹的行业:runDesign("Packaging › Sleeve", { L: 200 });如果没有其他设计使用该名称,也可以只写 runDesign("Sleeve")。 |
designs() |
库中的设计:每个为 {name, industry, description}。 |
designInputs(name) |
设计要求输入的内容:每个为 {name, label, kind, value, choices};kind 为 "number"、"text"、"toggle" 或 "choice"。 |
use(drawing) |
将某张图纸设为当前图纸(见下文)。 |
currentDrawing() |
当前图纸,或 null。 |
show(drawing) |
在应用中,在单独的窗口中打开该图纸(不保存);从命令行运行时,不做任何事。 |
batch(items, fn) |
对每个项目(文件路径、CSV 行……)调用 fn(item, index)。抛出错误的项目会记录在日志中,其余项目继续处理;在一次调用中打开的图纸会在调用后关闭。返回一个 {item, ok, result, error} 列表。 |
选择项的值是选项的名称("B flute")或其在列表中的位置(从 0 开始)。文件中没有的变量会被拒绝。
当前图纸
绘图 API——vars.L、newPoint、line、circle、command("…")、drawingInfo()、setNote、classify……——作用于当前图纸:最后打开或生成的图纸,或 use(drawing) 所选的图纸。修改的方式与交互窗口相同,因此所绘制的内容是参数化的。
const panel = newDrawing({ units: "in", industry: "SignMaking", name: "Panel" });
setVariable("W", 48);
setVariable("H", 24);
const a = newPoint("[0,0]");
const b = newPoint("[W,0]");
const c = newPoint("[W,H]");
const d = newPoint("[0,H]");
polyline([a, b, c, d], true);
panel.save("panel.piq");
图纸的函数
openDrawing、newDrawing 和 runDesign 返回一张图纸,它具有以下函数:
| 函数 | 含义 |
|---|---|
name、path |
其名称及其文件(在有文件之前为 null)。 |
variable("L") |
某个变量的值。 |
variables() |
其变量(不含隐藏变量),按名称列出,已计算。 |
inputs() |
其带标签的变量,形式与 designInputs 给出的相同。 |
setVariable("L", value)、setVariables({ L: 300, W: "L/2" }) |
设置变量,并重新计算图纸。可以是数字、true 或 false;文本变量为文本;选择项的选项;否则为表达式("L/2")。其标签保留。 |
evaluate("…") |
在图纸中计算一个表达式:evaluate("DISTANCE(P0,P2)")。 |
run("…") |
在图纸中执行图纸语言的语句,每行一条:run("FILLET(@1,@2,5)")。 |
info() |
关于图纸的所有已知信息,与 drawingInfo() 给出的相同:尺寸、合计、图层、排样…… |
notes()、setNote(name, value)、classification()、classify(…) |
其注释及其分类,与绘图 API 中相同。 |
regenerate() |
重新计算(每次修改后都会自动进行):其中某个块(IF、FOR……)出错时会抛出错误。 |
check() |
每条设计规则的检查结果:每个为 {rule, severity, message, elements, at}。 |
report(name, options, path) |
一份报表:{title, summary, tables, notes, text, csv},如果给出了 path,则写入该路径(.csv、.xlsx、.ods、.html、.pdf、.docx、.odt、.md、.json,否则为文本)。 |
export(format, path, options) |
导出(见下文):{path, format, extension, size, warnings}。 |
export(path, options) |
按文件扩展名所示的格式导出。 |
sendTo(profile, path) |
使用机器配置文件(其 id 或名称)导出,与 文件 › 使用机器配置文件发送 相同:使用其格式、其图层名称、颜色和笔、其后处理器、其文件名模式;导出到 path(文件夹或文件),否则导出到其自身的文件夹。 |
save(path) |
保存为图纸文件(如果名称没有扩展名,则为 .piq),未给出路径时保存到其自身的文件;然后运行保存扩展,与 文件 › 保存 相同。返回 {path, records}:每个保存扩展返回的内容,{extension, record, error}。 |
text() |
以图纸文本形式给出的图纸,与保存时相同。 |
use()、with(fn) |
将其设为当前图纸;或在其为当前图纸时调用 fn(drawing),然后恢复之前的当前图纸。 |
close() |
关闭图纸:之后不能再使用。 |
导出
format 是导出格式的名称,不区分大小写——pdf、svg、eps、ai、png、jpeg、webp、dxf、gcode、hpgl、cf2、ddes、lightburn、laserSvg、aamaDxf、tiledPdf、projectorPdf、wrapTemplatePdf、printCutPdf、printCutEps、gpgl、cuttingSvg、matCutterDxf、matCutterHpgl、dielinePdf、dstv、ifc、bendDxf、step、piq(exportFormats() 会列出它们)——或者文件扩展名(jpg、plt、nc、dd3、lbrn2、nc1、stp);null 表示使用路径的扩展名。参见文件格式。如果 path 是文件夹(已存在,或以 / 结尾),则文件以图纸名称保存在其中。每种格式都以其常用设置写出;options 可以给出:
| 选项 | 含义 |
|---|---|
margin |
图纸四周的留白,以点为单位(PDF、SVG、EPS、AI、图片)。 |
spotColours |
false:刀模线图层不使用专色。 |
textAsOutlines |
true:文字转为轮廓。 |
width、dpi、quality、transparent |
图片:横向像素数(或 dpi)、JPEG/WebP 质量、透明背景。 |
title |
写入文件的标题。 |
paper、overlap |
分页拼贴打印的纸张(A4、A3、Letter……)和重叠。 |
postProcessor、settings |
改为由后处理器(按其名称)写出,并使用其设置(其余为它自己的设置):export(null, "out/", { postProcessor: "Router 2", settings: { feed: 1200 } })。 |
文件
脚本只能在其文件夹(--folder,或在应用中为脚本所在的文件夹)中读写文件;不完整的路径从第一个文件夹读取。其他任何访问都会被拒绝。
| 函数 | 含义 |
|---|---|
args |
脚本名称之后的词:一个文本列表。 |
readText(path)、writeText(path, text)、appendText(path, text) |
文本文件(UTF-8)。 |
readJson(path)、writeJson(path, value) |
JSON 文件。 |
readCsv(path, { separator }) |
CSV 文件,每行一条记录,按标题行的名称取字段;数字作为数字。除非给出,否则分隔符为逗号、分号或制表符中在标题行中出现最多的那个。 |
writeCsv(path, rows) |
将记录(对象:第一条记录的名称作为标题)或列表写为 CSV 文件。 |
writeSpreadsheet(path, rows) |
将 writeCsv 所接受的行按路径的扩展名写为 Excel 工作簿(.xlsx,Numbers 和 Google 表格也能打开)、OpenDocument 电子表格(.ods,LibreOffice 的格式)或 CSV:数字仍为数字,标题行加粗。 |
listFiles(folder, pattern, all) |
文件夹中的文件("*.piq";all:也包括其子文件夹中的文件),完整路径,按顺序排列。 |
exists(path)、makeFolder(path) |
文件或文件夹是否存在;创建文件夹。 |
joinPath(a, b, …)、baseName(path) |
连接路径;不含文件夹和扩展名的文件名。 |
log(…)、print(…)、console.log(…) |
输出内容:输出到输出流或交互窗口。文本以外的值以 JSON 写出。 |
在文件夹中写入文件时会创建该文件夹。再次写入的文件会被替换。
错误
出错的情况——文件不被允许或不存在、图纸中没有的变量、无法执行的语句、无法识别的格式——都是 JavaScript 错误,带有说明原因的消息。可以用 try … catch 捕获它以继续运行,或者让它停止脚本:此时会给出脚本的名称和行号(orders.js, line 12: …),退出代码为 1。batch 会捕获每个项目的错误。
for (const file of listFiles("in", "*.piq")) {
try {
const d = openDrawing(file);
d.export("dxf", "dxf/");
d.close();
} catch (e) {
log("Not exported:", file, e.message);
}
}
示例:为 CSV 文件的每一行生成一个盒子
应用的 Extensions\Automation 文件夹中的 box-sizes.js(附带一个用于试用的 box-sizes.csv)为每一行盒子尺寸(名称、L、W、D 和纸板)生成一个普通开槽箱,将其写为 PDF 和 DXF 并保存,再写出 made.csv,其中包含每个展开料的尺寸和切割长度,供订单系统读回:
PiQ run box-sizes.js box-sizes.csv out
const made = batch(readCsv(args[0]), row => {
const values = { L: row.L, W: row.W, D: row.D };
if (row.board) values.T = row.board;
const box = runDesign("Packaging › FEFCO 0201 Regular slotted container", values);
box.export("pdf", joinPath(args[1], row.name + ".pdf"));
box.export("dxf", joinPath(args[1], row.name + ".dxf"));
box.save(joinPath(args[1], row.name + ".piq"));
return box.info().totals;
});
writeCsv(joinPath(args[1], "made.csv"),
made.map(m => ({ name: m.item.name, ok: m.ok, width: m.ok ? m.result.width : "", error: m.error ?? "" })));