繁體中文
English 简体中文 繁體中文
Methodox 首頁

指令碼

指令碼是一個 Command:在你執行時更改文件的 Lua、C# 或 Python 程式碼,其更改作為一個可復原的步驟。指令碼可在 Impulse、Formula、Expo 和 Nu 中從 Scripts 窗格或命令列執行。Divooka 圖的 Routine 也是指令碼,它會在同一窗格的圖編輯器中開啟。

Scripts 窗格

Tools ▸ Scripts(Alt+F11)會在底部托盤中開啟 Scripts 索引標籤:左側是文件的指令碼,中間是編輯器,右側是 Output 和 Problems 索引標籤。

Nu 的三角形圓環下方的 Scripts 索引標籤,旁邊是 Immediate 索引標籤:列表中的 CircleOfTriangles.lua、帶行號和語法著色的 Lua 編輯器,以及旁邊的 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 中的一個值。關於退出程式碼,請參閱命令列與轉換。