指令碼
指令碼是一個 Command:在你執行時更改文件的 Lua、C# 或 Python 程式碼,其更改作為一個可復原的步驟。指令碼可在 Impulse、Formula、Expo 和 Nu 中從 Scripts 窗格或命令列執行。Divooka 圖的 Routine 也是指令碼,它會在同一窗格的圖編輯器中開啟。
Scripts 窗格
Tools ▸ Scripts(Alt+F11)會在底部托盤中開啟 Scripts 索引標籤:左側是文件的指令碼,中間是編輯器,右側是 Output 和 Problems 索引標籤。

列表
列表首先顯示文件的函式指令碼,然後是其 Command,再然後是其圖文件,每項都帶有表示其型別的圖示和表示其語言的顏色。右鍵按一下指令碼,或使用以下按鍵,可以:
- 新建指令碼:工具條上的 New script、
Insert或Ctrl+N,使用工具條列表中所選的語言(Lua、C# 或 Python),開頭帶有一行指明應用程式的程式碼; - 重新命名:
F2; - 複製:
Ctrl+D; - 刪除:
Delete,會先詢問。
指令碼儲存到文件後,以上每項操作都是視窗 Edit ▸ Undo 中的一個步驟。
編輯器
編輯器為 Lua、C# 和 Python 提供語法著色和行號,突出顯示插入點所在的行以及與其旁邊括號相匹配的括號,並按照語言的程式碼塊需要縮排新行。
Ctrl+Space提供根據物件模型生成的補全建議;輸入.(在 Lua 中為:)也會提供補全建議。- 只要編輯器擁有鍵盤焦點,
Ctrl+F和Ctrl+H就會在指令碼中(而不是在文件中)尋找和替換;F3尋找下一個匹配項。Ctrl+G轉到某一行,Ctrl+/註解或取消註解所選的行,Tab和Shift+Tab增加和減少其縮排。 - 當你暫停輸入時,指令碼會被檢查:錯誤會帶底線,懸停時顯示其訊息,並列在 Problems 索引標籤中,按一下即可轉到該行。
執行
- Run(
Ctrl+Enter)針對開啟的文件執行指令碼;Ctrl+Shift+Enter只執行所選的行。按鈕旁邊的狀態會說明執行耗時,或者說明執行失敗並已回滾。 - 對於圖文件,Run 旁邊的列表用於選擇要執行哪個 Routine。
- Save 把指令碼作為可復原的更改儲存在文件中,由 File ▸ Save 寫入磁碟;Export 把一份普通副本寫入你選擇的檔案,即使文件從未儲存過也可以。早期版本中的指令碼資料夾(
<document name>.scripts\)會在文件開啟時被納入文件。 - Python environments and packages 按鈕用於管理 Python 可以使用的包;參見 Python。
當指令碼失敗時,輸出會指出檔案、行和錯誤,編輯器會選中該行。一次執行是 Edit ▸ Undo 中的一個步驟,以指令碼的名稱標註,因此 Ctrl+Z 會撤回它所做的一切。
Smart Objects 索引標籤也會列出文件的指令碼,其中的 Show Definition 會開啟計算某個儲存格或智慧物件的指令碼。
即時模式
Tools ▸ Immediate 會開啟 Immediate 索引標籤。它是底部托盤中位於 Scripts 旁邊的一個獨立索引標籤,因為它作用於文件,而不是正在編輯的指令碼。它會立即針對視窗的文件執行你輸入或貼上的內容,可使用 Lua、C# 或 Python(在其列表中選擇):用於查詢文件、嘗試某個呼叫,或在不編寫指令碼的情況下進行一次性編輯。
Enter執行該行,表示式的值會列印在其下方。Shift+Enter(或在 Python 中,以冒號結尾的行)會開始新的一行,Ctrl+Enter執行整個程式碼塊。↑和↓逐條瀏覽你之前執行過的內容。- 某條輸入定義的內容會保留給下一條輸入使用,直到你更改語言或文件。
每條輸入都是一個事務,因此按一次 Ctrl+Z 即可撤回。即時模式是你自己輸入的內容,而不是文件的程式碼,因此在兩個版本中都擁有完全存取權限:完整的語言、無需詢問即可使用宿主的呼叫,在 Python 中還包括 .NET 橋接和你的環境中的包。
第一個指令碼
-- Format all tables: thin grey borders, a shaded bold header row, and the header repeated at the top of every page the table runs onto.
local count = 0
for t in doc.tables do
t:setBorders({ style = "single", width = 0.5, color = "#7F7F7F" })
t:shadeRow(1, "#D9E2F3")
t:boldRow(1)
t.headerRows = 1
count = count + 1
end
print(string.format("Formatted %d table(s).", count))
用 C# 編寫的相同指令碼:
int count = 0;
foreach (Table table in Doc.Tables)
{
table.SetBorders(new Dictionary<string, object?> { ["style"] = "single", ["width"] = 0.5, ["color"] = "#7F7F7F" });
table.ShadeRow(1, "#D9E2F3");
table.BoldRow(1);
table.HeaderRows = 1;
count++;
}
Print($"Formatted {count} table(s).");
兩者都是套件 Examples\Automation 資料夾中的示例:Impulse\FormatAllTables.lua 和 .csx、Formula\SummarySheet.lua(一個彙總工作表,其中包含來自第一個表格的即時合計)、Expo\DeckFromWorkbook.lua(為活頁簿的每個工作表生成一張投影片),以及 Nu\CircleOfTriangles.lua 和 .py(一個三角形圓環,每個三角形都沿其半徑方向旋轉)。
物件模型
始終可用的名稱有三個:app(應用程式)、doc(指令碼所針對的文件)和 session(執行本身)。在 C# 中,它們是 App、Doc 和 Session,Doc 具有文件自身的型別,Print(...) 寫入輸出。在 Lua 中,成員採用 lowerCamel 形式(doc.sheets),方法使用 : 呼叫(t:boldRow(1)),集合使用 for x in collection do 遍歷。在 Python 中,成員採用 snake_case 形式(sheet.used_range),print 寫入輸出。在每種語言中,計數都從 1 開始。
app 和 session
| 成員 | 說明 |
|---|---|
app.version |
Methodox Office 版本 |
app.arguments |
在命令列中給出的 --arg 值 |
app:open(path) |
開啟另一個 .xlsx、.docx 或 .pptx;除非指令碼儲存它,否則在執行結束時會不儲存而關閉 |
app:new(kind) |
一個新文件:"formula"、"impulse" 或 "expo" |
doc:save(), doc:saveAs(path), doc:close() |
儲存或關閉指令碼開啟的文件 |
session.commands |
應用程式自身的命令;見下文 |
param.Name(C#:Param["Name"]) |
一個 Document Parameter |
host.get(url), host.getJson(url), host.getImage(url), host.readText(path)(C#:Host.Get 等) |
授予的網路和檔案存取權限 |
Formula
| 物件 | 主要成員 |
|---|---|
doc(活頁簿) |
sheets, names, tables, range("Sheet1!A1:C3"), calculate() |
| sheets | count, [1] 或 ["Sales"], find(name), add(name, before) |
| sheet | name(重新命名會更新公式), range("A1:C3"), cells(row, column), usedRange, tables |
| range | value(填充區域), values(由值組成的行), formula(以相對引用填充), formulas, text(按顯示內容), format, address, read(), write(values, { header = true }), offset(r, c), resize(r, c), currentRegion, clear() |
| range format | bold, italic, fontSize, numberFormat, fontColor, fill, horizontalAlignment |
| names | add(name, refersTo), remove(name), [name](帶 refersTo 和 range) |
| tables | add(range, name, { style = "TableStyleMedium2" });表格具有 name, range, headerRange, dataRange, columns, rows()(按列名組織的記錄), column(name) |
寫入儲存格的值就是值:作為值寫入的 "=1+1" 是文字。公式通過 formula 和 formulas 寫入,它們會在更改任何內容之前檢查每個公式。
Impulse
| 物件 | 主要成員 |
|---|---|
doc(文件) |
paragraphs, tables, styles, text, find(text, { matchCase, wholeWord, regex }), replace(text, replacement, options), addTable(rows, columns, values), smartObjects |
| paragraphs | count, [i], last, add(text, style) |
| paragraph | text, style, alignment, spaceBefore 和 spaceAfter, lineSpacing, runs, characters(start, length), insertAfter, insertBefore, delete() |
| text range(一個文字段) | text, bold, italic, underline, fontName, fontSize, color, highlight |
| table | rowCount, columnCount, cell(r, c), read(), write(values), headerRows, style, setBorders(...), shadeRow(row, color), boldRow(row), delete() |
smartObjects |
參見智慧物件 |
doc:replace 是一個復原步驟,並返回替換的數量;使用 regex 時,替換文字中的 $1 表示第一個分組。
Expo
| 物件 | 主要成員 |
|---|---|
doc(簡報) |
slides, layouts, slideWidth, slideHeight(以磅為單位) |
| slides | count, [i], add(layout, at),使用佈局名稱,例如 "Title and Content" |
| slide | title, titleShape, bodyShape, shapes, placeholder(kind), notes, layout, background, duplicate(), moveTo(position), delete() |
| shapes | addTextBox(text, left, top, width, height), addShape(preset, left, top, width, height, text), addChart(kind, data, left, top, width, height, options), find(name) |
| shape | name, text, left, top, width, height, fill, bold, italic, fontSize, color, alignment, delete() |
| chart | setData(rows),它會保留每個系列的繪製方式,以及值範圍、系列顏色和類別標籤的位置 |
Nu
| 物件 | 主要成員 |
|---|---|
doc(繪圖) |
pages, activePage, selection, layers, pageWidth, pageHeight, mm(millimetres)(將毫米換算為磅), describe(), count() |
| pages | count, [i] 或 ["Name"], find(name), add(name, at) |
| page | index, name, width, height, centerX, centerY, background, shapes, shapesAt(x, y), shapesIn(left, top, width, height), duplicate(), moveTo(position), delete() |
| shapes | count, [i] 或 ["Name"], find(name), all(), ofKind(kind), named(prefix), addShape(preset, left, top, width, height, text), addTextBox(text, left, top, width, height), addLine(x1, y1, x2, y2), addConnector(from, to, kind), group(shapes) |
| shape | name, kind, text, left, top, width, height, centerX, centerY, rotation, flipHorizontal, flipVertical, moveTo, moveBy, centerOn(x, y), resize, rotateBy(degrees), rotateAround(x, y, degrees), fill, fillOpacity, line, lineWidth, startArrow, endArrow, bold, italic, fontSize, fontName, color, alignment, hidden, layer, isGroup, children, ungroup(), isConnector, startShape, endShape, connectors, duplicate(dx, dy), bringToFront(), sendToBack(), bringForward(), sendBackward(), delete() |
位置和大小以磅為單位,從頁面左上角開始計算;在兩個形狀之間新增的連線線會在它們移動時保持粘附。每次更改都是本次執行的那一個復原步驟的一部分。
Impulse 文件還支援圖片(doc:addPicture(at, bytes, width))、邊界,以及表格的列寬、內邊距、邊框、填充和對齊方式。物件模型中尚未提供:刪除 Formula 工作表;Formula 和 Impulse 中的圖表;域;Expo 簡報中尚不存在的佈局;Nu 中的圖片、表格和漸層。
呼叫應用程式的命令
選單上的一切都是帶有名稱的命令,指令碼可以呼叫它們:
session.commands:execute("format.bold")
print(session.commands:isAvailable("edit.undo"))
for id in session.commands:list() do print(id) end
describe(id) 列出命令的參數,execute 以表的形式接受這些參數。需要對話方塊或視窗選擇內容的命令可以從 Scripts 窗格執行,但不能從在命令列上執行的指令碼中執行,並會說明這一點。
事務
一次執行是一個事務。如果指令碼失敗,或它呼叫的命令被拒絕,本次執行所做的一切更改都會回滾,文件恢復原狀;失敗的執行所做的任何事情都無法被儲存。讀取能看到本次執行自己的寫入:指令碼寫入某個儲存格後,讀取該儲存格的公式會得到新值。在 Lua 中,pcall 可以捕獲拒絕,執行會繼續進行,因為被拒絕的操作不會更改任何內容。
從命令列執行
MethodoxFormula --script SummarySheet.lua --open Sales.xlsx --save-as Summary.xlsx
MethodoxExpo --script DeckFromWorkbook.lua --arg Sales.xlsx --save-as Sales.pptx
MethodoxNu --script CircleOfTriangles.py --save-as ring.pptx
mos --script FormatAllTables.lua --save-as Report-formatted.docx Report.docx
圖 Routine 以相同方式執行,在其圖文件名稱之後指定:--script "Report.dvj#StampRegion"。--open(使用 mos 時則為最後指定的文件)是指令碼所針對的文件;如果沒有指定,指令碼會得到一個新文件。--save-as 僅在指令碼成功時儲存結果;除非指令碼本身呼叫 doc:save(),否則開啟的檔案永遠不會被覆蓋。每個 --arg 是 app.arguments 中的一個值。關於退出程式碼,請參閱命令列與轉換。