# EMILY.RPA 產品文件
> EMILY.RPA 是 BILINK CORP. 開發的跨平台流程自動化機器人 (RPA) 軟體,可操作網頁與桌面軟體的使用者介面,讓缺乏 API 或 SDK 的系統也能達成自動化。
本檔案為 https://docs.emily.tips 全站文件的 Markdown 全文,供大型語言模型一次載入檢索與引用。每份文件以 Source 標示其原始網址。
---
# 歡迎使用 EMILY.RPA
Source: https://docs.emily.tips
> EMILY.RPA 是跨平台的流程自動化機器人 (RPA) 軟體,支援 Windows、macOS 與 Linux。本頁說明系統與硬體需求、14 天免費試用、下載安裝與帳號註冊流程。
EMILY.RPA 是一個跨平台的流程自動化機器人 (Robotic Process Automation) 應用軟體,主要用在自動化有明確規則的重複性工作,特別適合在耗時、容易產生人為錯誤、需要全天候執行的業務上。EMILY.RPA 的特色在它可以操作使用者介面,例如網頁或桌面軟體,因此缺乏 API 或 SDK 的系統也能達成自動化。
它支援 Windows 10 以上、MacOS 11.6 以上、以及主流的 Linux 桌面作業系統包含 Ubuntu 20.04、Fedora 24 還有 Debian 8 以上的所有版本。最低的硬體需求為雙核心的 CPU 例如 Intel Core i5 或其他同等級產品,記憶體至少 8GB,儲存空間至少 20GB。如果會執行桌面自動化或 PowerShell 等記憶體需求較大的功能,則建議記憶體增加到 16GB 以上,同時需注意啟動 EMILY.RPA 時的可用記憶體至少需要 2GB,以避免因為記憶體不足而產生閃退等非預期現象。
EMILY.RPA 提供 14 天免費試用,試用期滿後自動化執行的相關功能會關閉,但設計與測試等功能可以繼續使用。在開始下載前,必須先確認安裝的電腦設備可以連到 https://emily.tips (軟體授權伺服器) 與 https://cdn.emily-rpa.com (版本更新伺服器) 這兩個網站,如果無法連上可以聯繫您的組織網路管理員,通常是被防火牆阻擋了,需要網路管理員將以上兩個網域加入防火牆放行的白名單,並允許憑證鏈驗證所需的 OCSP、CRL、CA repository 流量。
現在我們就開始一步步的完成 EMILY.RPA 機器人的安裝程序。
### 註冊帳號
下載的安裝軟體完成安裝後的第一個畫面就如下圖,`ENDPOINT` 欄位會預先填上 `https://emily.tips` 作為授權伺服器端點不必更動;如果您的組織採用的是落地部署,則端點應該是與下載安裝軟體相同的網站,需要自行填入。

`EMAIL` 欄位需要填入您的電子郵件信箱,它將被用來作為您在 EMILY.RPA 註冊的帳號識別碼。在按下「**傳送PIN碼**」後,通常需要等候1~3分鐘,您輸入的信箱將收到一封內含六位數字 PIN 碼的郵件,請將 PIN 碼回填到 `PIN` 欄位並點擊「**驗證PIN碼**」,就能完成註冊程序。

如果沒有收到內含 PIN 碼的郵件,先檢查是否被分類到廣告或垃圾郵件信箱,再聯繫您的組織郵件伺服器管理員,檢查是否信件被過濾規則給阻擋在伺服器端。
### 檢查帳號
完成註冊後,到主界面下方功能選擇區切換到「帳號設定」頁,在版本資訊下方就是剛才註冊的帳號與有效期限,點擊它可以進入「帳號詳情」頁:

在帳號詳情頁的頁首區可以為您的機器人取一個暱稱。下方內容包括有效期限,並提供線上刷卡購買授權;「授權電腦數」代表您的帳號可以在幾台電腦上同時開啟 EMILY.RPA 機器人,一個帳號預設只有一個授權,這代表同一時間您的帳號只能在一台電腦設備上啟動 EMILY.RPA 機器人,若不同時間啟動則無限制。下方的「群組」為企業選購的功能,群組內的帳號可以互相分享自己設計的自動化流程,我們稱為「技能」。

當遇到以下畫面表示您有其他用同個帳號註冊 EMILY.RPA 電腦正在開啟中,已達您的帳號「授權電腦數」,需要先將其他開啟中電腦的 EMILY.RPA 關閉才能在目前電腦登入使用。也可以聯繫我們採購複數電腦的授權,這個功能提供企業選購。

---
# 使用者介面導覽
Source: https://docs.emily.tips/user-interface
> EMILY.RPA 主界面導覽:我的技能、全自動觸發、執行結果與帳號設定四個功能頁的操作說明。
EMILY.RPA 主界面的頁尾是主要功能選擇區,可以切換成「**我的技能**」,「**全自動觸發**」,「**執行結果**」與「**帳號設定**」四個功能頁,頁首及內容會隨著功能頁的同而改變。隨著使用累積資訊,可以拖曳視窗左右邊界增加寬度,但高度是固定無法改變的。




在 MacOS 桌面上方的選單列或 Windows 桌面下方的系統匣可以找到一個閃電圖示,點擊閃電開啟選單後可以「顯示」或「隱藏」 EMILY.RPA 的使用介面,此時您可以使用桌面而 EMILY.RPA 會在背景執行。需注意在執行「**桌面自動化**」功能時 EMILY.RPA 會控制滑鼠鍵盤操作桌面,使用者如果也在操作會相互干擾,也容易造成自動化執行失敗。選單中的「檢查更新」可以立即檢查是否有更新版本,另外 EMILY.RPA 開啟時也會自動觸發檢查。點擊「客戶支援」選項會開啟網頁提供使用者發送客戶支援請求,但僅限於產品使用與收費方式等非技術性問題。

### 我的技能
EMILY.RPA 將「自動化流程」稱為「技能」,而功能頁「**我的技能**」就是用來管理本機上的所有技能。點擊頁首「**訓練技能**」圖示會進入訓練模式,按 ESC 鍵或滑鼠點擊對話框以外區域可以取消。在「訓練模式設定」中可以為技能所屬的 `技能群組` 命名,空白也是一個群組,同一個群組會共享同一個瀏覽器 cookie 資料庫,這在需要登入的網站很有用,通常這些網站在登入後會將狀態寫入 cookie 以保持登入的狀態。在 EMILY.RPA 中每一次技能執行時會配置對應的「工作資料夾」,訓練模式下開發技能時,「工作資料夾」會固定在一個名為 `tmp` 的資料夾,這是為了方便開發技能時可以簡化輸出入檔案的管理與重複使用,`清除工作資料夾` 會將 `tmp` 資料夾中檔案都刪除;但在執行模式下,每一次技能的執行都會新產生一個專屬的「工作資料夾」,這是為隔離不同執行的結果,並讓使用者可以回溯存取該次執行的輸出入檔案。

完成「訓練模式設定」後,會開啟一個訓練用的瀏覽器視窗,使用者可以在 `Web Automation` 網址列填入目標網頁的網址來開始網頁自動化的流程設計,或選擇下方的自動化模組,此時主界面轉為流程步驟新增、修改、刪除的功能。



在「**我的技能**」頁首的「**下載技能**」圖示是技能庫的入口,技能庫(Skill Hub)保存著使用者開發的所有技能,以及企業群組中其他使用者分享的技能,本機端刪除的技能可以從技能庫重新下載安裝。如果有選購企業群組,技能每次上傳都會加入版本歷史,達到版本控制的目的。


### 全自動觸發
在「**全自動觸發**」頁包含「排程觸發」,「郵件觸發」,「API 觸發」,「檔案觸發」,「網頁觸發」的設定與管理功能,設定完成後必須點擊「啟動觸發器」EMILY.RPA 才會進入全自動模式,這時觸發才會作動。

進入全自動模式後,所有符合觸發條件的技能會被排入工作佇列中依序執行,一次執行一個工作,在退出全自動模式前無法使用 EMILY.RPA 的其他功能以確保全自動模式的穩定,例如修改觸發規則或是進入「訓練模式」都需要退出全自動模式。

### 執行結果
這個頁面保存執行技能後的結果資訊,包含該技能執行的工作資料夾,頁首提供「通知頻率」與「執行結果保存期限」的設定。

### 帳號設定
在「**帳號設定**」頁面中,版本資訊內提供版本更新與使用者介面語言的設定。帳號詳情內提供帳號與授權相關資訊,並提供線上購買授權的功能。其他包含設定Google雲端應用的憑證,定義變數,加密文字資料等。

---
# 動手設計一個技能
Source: https://docs.emily.tips/design-skill
> 動手設計第一個 EMILY.RPA 技能:以網頁自動化查詢維基百科關鍵字、將結果存成 PDF 並複製到桌面的完整教學。
現在我們來動手設計一個簡單的技能,先到維基百科網站 https://www.wikipedia.org/ 查詢關鍵字 `world wide web`,再將查詢結果存成 PDF 檔案,最後放到螢幕桌面上。這個技能將會用到操作 EMILY.RPA 瀏覽器的網頁自動化,以及一個將檔案複製到桌面的自動化模組,透過這個練習可以很快的了解設計模式的運作原理。
### 進入訓練模式
首先在「我的技能」頁上方點擊「訓練技能」圖示,在「訓練模式設定」對話窗中的 `技能群組` 填入 `練習技能`,這會將我們接下來創建的技能歸類到 `練習技能` 這個群組,「清除工作資料夾」可以不需要清除,因為這時訓練模式的工作資料夾 `tmp` 應該是空的,接著按「開始」。

### 準備網頁自動化
進入「訓練模式」後會自動開啟一個瀏覽器視窗,在 `Web Automation` 網址列填入 `https://www.wikipedia.org/` 後按下 `ENTER` 鍵,瀏覽器就會載入維基百科的首頁。

這時你應該會看到下圖的畫面,左邊的主視窗介面上半部是指令列表,下半部是許多工具的圖示,而瀏覽器視窗則是維基百科的首頁。

### 錄製網頁操作步驟
現在我們開始跟網頁互動,讓 EMILY.RPA 記錄整個互動流程的每一個步驟。確認鍵盤輸入游標是在網頁搜尋框中,如果沒有也可以用滑鼠點擊搜尋框的中間位置讓鍵盤輸入游標出現,接著輸入 `world wide web`。

輸入完成後就按 `ENTER` 鍵,這時瀏覽器會載入新網頁,也就是如下圖的搜尋結果頁。而主界面視窗的指令列表也多了剛才與網頁互動的每個步驟,這就是流程設計的基本原理。

### 使用「列印輸出」工具
現在我們要將網頁輸出成 PDF 檔案。在主界面視窗下方找到「列印輸出」工具圖示後點擊它,選擇「PDF」後按確定。


這時會有一個「列印網頁」對話框彈出,將儲存檔案名稱改為 `wiki.pdf`,預設的存檔資料夾應該是 `tmp` 不需要更改,直接按「儲存」。

這時點擊主視窗下方工具圖示「工作資料夾」會帶出檔案管理員視窗,預設資料夾就是 `tmp` 工作資料夾,然後檢查網頁內容是否被正確地儲存到 wiki.pdf 檔案中,檢查後可以將檔案總管關閉。

### 使用「自動化模組」
EMILY.RPA 除了網頁自動化之外,其他的自動化控制都屬於「自動化模組」。點擊主界面的「回到設計首頁」工具設計首頁就會出現,我們點選「匯出工作資料夾」。

在「匯出工作資料夾」模組介面中,先點擊「PICK」按鈕選擇桌面資料夾作為匯出的目標資料夾,再點擊「ADD NO-CODE COMMAND」後選擇「篩選檔案後匯出」指令,`HINT` 部分填入方便我們理解的 `匯出輸出的PDF`,下方 `FILTER` 填入 `wiki.pdf` 後點擊「OK」。

現在「匯出工作資料夾」模組已經設定為:有一個無程式碼指令「篩選檔案後匯出」,內容是將 wiki.pdf 匯出到指定的資料夾,也就是 `FOLDER` 選擇的桌面資料夾。模組設定的最後一個步驟是點擊右上方的「SAVE」讓這個模組的設定錄製到技能中。

### 完成技能錄製
當你按下自動化模組的「SAVE」按鈕後,主界面將模組作為一個指令加入流程中,EMILY.RPA 的技能就是由各種指令的錄製來描述流程的操作,流程中可以由多個網站與多個自動化模組構成,沒有數量上的限制,因此可以完成複雜且冗長的工作。當流程已經錄製完所有指令,就可以按下「結束」。

最後一步是為這個錄製好的技能填寫 `名稱` 與 `說明` 欄位,這兩個雖然不是必要,但是對未來管理與進一步應用很有幫助,建議仔細填寫。在介面上放頁首區可以點擊「測試」,EMILY.RPA 會按照剛才錄製的指令一步步執行以確認流程有達成目標,然後才點擊測試旁的「上傳」按鈕將技能上傳備份到雲端技能庫(SKILL HUB),同時也會儲存到本機。

恭喜!你剛完成了第一個 EMILY.RPA 的自動化技能。你的主界面「我的技能」功能頁會出現剛才上傳的技能,點擊技能右邊的播放鍵可以執行它

或者點擊技能項目本身會出現選單,提供這個技能的相關的管理功能,如:「設定」名稱、說明、群組、輸入檔案;「調整」流程中的指令包括新增或刪除;或是將這個技能以排程、API 或網頁觸發;「刪除」技能,但可以從技能庫重新下載備份的版本;「上傳」更新的技能到雲端技能庫;最後是執行技能並指定它的工作資料夾。

---
# 帳號設定相關功能
Source: https://docs.emily.tips/config
> EMILY.RPA「帳號設定」功能頁說明:版本更新、版本號碼、帳號名稱、授權有效期限與其他相關設定。
EMILY.RPA 的帳號授權、版本更新、以及其他設定都在「**帳號設定**」功能頁。可更新版本(如果有的話)、版本號碼、帳號名稱與授權有效期限可以直接在頁面項目上找到。

### 版本資訊
點擊版本項目後會進入版本詳情頁。如果有可更新版本,頁面會出現「**立即更新**」與「**手動下載**」兩個選項,其中如果立即更新無法成功可以改用手動下載,原因是防毒軟體或端點保護軟體可能禁止下載可安裝執行的檔案。手動下載時要確保防火牆允許 cdn.emily-rpa.com 這個網域的連線。

使用者介面的語言可以點擊「**選擇語言**」進入選單,目前支援英文、繁中、日文三種語言。

### 帳號授權
點擊帳號項目後會進入帳號詳情頁,內容包含「**有效期限**」、「**授權電腦數**」、「**群組**」以及「**授權記錄**」。其中授權電腦數與群組需要企業方案才能設定,授權電腦預設都是一台,也就是同時間只能在一台電腦打開 EMILY.RPA,群組功能則是提供企業多個帳號間的技能共用與權限管理,可聯繫您的商務窗口。

「**購買授權**」提供單次線上刷卡購買帳號授權,可以自行選擇授權期限長度,到期只會通知不會自動扣款。如果需要報帳可以在「**選擇載具**」選統一編號,或者選載具兌獎。

如果您是企業方案的客戶,需透過商務窗口為您的授權採購交付授權檔,授權檔的檔名通常像是 `8e3fa754-e8e0-4836-b452-d9be3978b7d6-39f9ff5e8031.json`,點擊「**安裝授權**」後會出現檔案總管選擇授權檔案,選取後會出現授權的內容,這時點擊「**安裝授權**」才會開始安裝。


當有流程設計、部署或除錯等技術問題時,可以點擊「**技術服務**」按鈕開啟付費技術服務請求頁面。如果尚未儲值,也可以透過該頁面通知客戶專員與您聯繫。


如果安裝 EMILY.RPA 的電腦不想再用目前帳號了,可以在下方「**登出**」帳號。請注意登出帳號日後如果再註冊登入本機,安裝的技能必須重新從技能庫下載。

### 觸發器選項
觸發器「**啟動時進入全自動模式**」開關打開後下次啟動 EMILY.RPA 就會直接進入全自動模式,配合作業系統的「**開機自動登入**」與「**啟動執行應用程式**」設定可以達成一開機就讓 EMILY.RPA 全自動的目標。

### 預設變數
「**預設變數**」可以將常用的輸入資訊儲存成一個變數,可以用在自動化各種系統的帳號、密碼、或金鑰上。企業方案另外還提供群組共用的變數,可以讓群組內帳號使用而不會外洩明碼。

### 保護資料
進入「**保護資料**」對話框可以輸入需要保護的文字資料,例如密碼,EMILY.RPA 會用作業系統保護的金鑰加密,然後儲存成密文。這個密文文字檔使用在技能中才會被即時解碼,不會留存明碼。

### Google API Key
在多個自動化模組中會使用到 Google 服務,例如 Google Drive 雲端硬碟與 Google Sheets 試算表等,會需要設定 Google Cloud Platform 上申請的憑證檔,並對憑證上的 Google 服務帳號郵件地址開放存取權限。使用下方「**指定GCP憑證檔**」設定申請好的 JSON 檔案,並點選「**憑證電子郵件**」取得憑證上的郵件地址,就可以在 Google Drive 或 Google Sheets 中開放讀寫權限給該電子郵件,相關自動化模組才有權限操作。

---
# 深入網頁自動化
Source: https://docs.emily.tips/web-automation
> 深入說明 EMILY.RPA 網頁自動化的運作原理、網頁元素定位方式與設計技巧。
網頁自動化是 RPA 相當常見的應用,除了外部資訊的搜集之外,現代企業所使用的軟體或資訊系統幾乎都以網站方式來部署,中小企業也大量的採用 SaaS 服務,解決的問題從行銷,業務,人資,法務到財務等包羅萬象,因此 RPA 的能力很大的程度取決於對網頁的自動化能力。
## 運作原理
大多數 RPA 的做法是要求使用者安裝瀏覽器的擴充元件來達成操控瀏覽器的目的,這個擴充元件可以看到使用者瀏覽器中的網頁,也能接收 RPA 軟體的指令插入程式碼到網頁中,但隨著瀏覽器的資安與隱私保護的要求越來越高,擴充元件的權限不斷收縮,造成網頁自動化的能力受限,甚至常因瀏覽器版本更新造成自動化失敗。另一方面,讓 RPA 操控使用者平日使用的瀏覽器會增加不想被自動化網站的外洩風險,甚至需要擔心被惡意操控,例如個人的網路銀行。
為了徹底解決這個問題,EMILY.RPA 內建了 Chromium 瀏覽器核心,毋需使用者的 Chrome、Edge、Firefox 或其他瀏覽器就能達成網頁自動化,並提供豐富的工具來簡化流程的設計。也因為與使用者平日使用的瀏覽器分開,使用者沒有用 EMILY.RPA 登入過的網站資訊就沒有資訊外洩或被操控的風險。
## 網頁自動化工具集
在訓練模式主界面的下方圖示區提供多種工具,除了「**回到設計首頁**」與「**工作資料夾**」之外,其他都會在流程中錄製相對應的指令。

如果想要批次多選指令以刪除或忽略,點擊指令列下方的「**選擇指令**」,再選擇介面底部的動作。

###
匯入檔案
選擇並匯入指定來源檔案到工作資料夾,並可指定在工作資料夾內的檔名。其中來源檔案欄位可以夾帶 **%FILENAME%** 變數,執行時會以工作資料夾內檔名為 **FILENAME** 的 TXT 檔案內容取代,達到動態指定的效果。
###
插入子技能
選擇一個技能,插入流程中成為一個步驟。當 EMILY 機器人執行到這個步驟,會將這個子技能中的所有步驟載入依序執行。勾選**使用新瀏覽器執行子技能**會在執行時期開啟一個新瀏覽器視窗執行選擇的子技能,而選擇的子技能也能有獨立的循環工作;若不勾選則子技能會執行在同一個瀏覽器視窗中,也需遵守**禁止巢狀循環工作**的規則。放棄插入子技能只要按鍵盤 ESC 鍵即可。

###
循環工作
循環工作提供**循環表格工作**與**循環條件工作**兩種方式,需遵守**禁止巢狀循環工作的規則**。
點擊**循環工作**並選擇 CSV 格式檔案就會進入**循環表格工作**,表格中第一列資料的每個欄位值會被存入工作資料夾 TXT 檔,檔案命名方式為 row-columnName.txt,使用者可以存取這些存放欄位值的 TXT 檔案,並應用於循環內的流程步驟中,完成第一列資料的循環步驟錄製後,EMILY.RPA 會於執行模式下依照 CSV 每列資料依序執行循環流程一次。
若選擇的是 TXT 檔案則會進入**循環條件工作**,於循環內錄製的流程步驟在執行前會檢查指定的 TXT 檔案內容是否符合設定的條件,一旦不符合條件**循環工作**就會終止循環,因此使用者在訓練循環內流程步驟時,必須依照想要達成的規則明確的改寫 TXT 檔案內容。
###
前往網址
讓瀏覽器會到訓練模式首頁。
###
選取全部
將瀏覽器中游標所在元素的文字內容全部選取。
###
拷貝
將瀏覽器中被選取文字拷貝下來存入剪貼簿,同時也可以存檔在工作資料夾。
###
貼上
將剪貼簿中的文字貼到瀏覽器中游標所在位置。
###
插入文字
選擇一個 TXT 檔案,在瀏覽器中游標所在位置插入檔案文字內容。
###
執行腳本
在瀏覽器中選擇網頁目標節點,撰寫 JavaScript 腳本程式對其存取,通常用於細部操作網頁元素或是彈性擷取網頁資訊。選擇到的可能目標節點以腳本中變數 nodes\[] 陣列表示,並支援 [lodash.js](https://lodash.com/docs/) 與 [moment.js](https://momentjs.com/docs/) 工具函式庫以及 read(filename, encoding='utf8'), write(filename, content), remove(filename), repeat(true, delay=3000ms) 等工作資料夾處理函式。
```javascript
// 針對新聞網頁的新聞列表,擷取每則新聞摘要內容
nodes.forEach((node, index) => {
write('news-' + index + '.txt', node.innerText)
})
```
若想要執行腳本並等到腳本中的非同步函式完成才繼續下一個自動化步驟,可以再腳本中回傳 Promise 物件如下:
```javascript
// scroll 到頁面下方,頁面資料需要幾秒鐘時間才能載入完全
document.querySelector("div.bottom").scrollIntoView()
// 回傳一個 Promise 物件,下一個自動化步驟會等到 Promise 解決(resolve)再繼續
return new Promise((resolve) => {
setTimeout(() => {
write("page.txt", document.body.innerText)
document.querySelector("a.nextPage").click()
resolve()
}, 5000)
})
```
在腳本中也可以識別碼叫用其他技能,被叫用的技能會執行在目前的工作資料夾,並且會開啟新的瀏覽器視窗執行,因此同樣不受**禁止巢狀循環工作**的規則限制:
```javascript
// run() API 為非同步函式,回傳一個 Promise 物件,也可以串接
return run("96fcb9b5-e209-4051-b502-ffd142e31a87")
.then(() => run("bb0a7f40-47e8-40ad-a7f9-d839ee8bcc5d"))
```
或是在腳本中下載檔案到工作資料夾:
```javascript
// download(url, filename) API 為非同步函式,回傳一個 Promise 物件
return download("https://example.com/pricing.pdf", "price.pdf")
```
在腳本中可以使用 clipboard API 對作業系統剪貼簿讀取或寫入:
```javascript
// 寫入文字到剪貼簿
clipboard.writeText('hello')
// 讀取剪貼簿文字
console.log(clipboard.readText())
// 寫入HTML到剪貼簿
clipboard.writeHTML('hello
')
// 讀取剪貼簿HTML
console.log(clipboard.readHTML())
```
如果想利用腳本操作滑鼠,可以利用以下同步函式:mouseEnter(node), mouseMove(node, x, y), mouseLeave(node), mouseDown(node, x, y), mouseUp(node, x, y), mouseClick(node), mouseDblClick(node), mouseContextmenu(node, x, y)
```javascript
// simulate mousedown and mouseup
let node = document.querySelector("BUTTON#send")
mouseDown(node)
mouseUp(node)
```
也可以利用 DA mouse 非同步函式實際控制滑鼠或鍵盤:
```javascript
// control mouse actions
return mouse.enable(true)
.then(() => mouse.move(nodes[0], 0, 0))
.then(() => mouse.clickLeft())
.then(() => mouse.enable(false))
```
```javascript
// control keybaord actions
await keyboard.enable(true) // enable(true) 會將瀏覽器視窗放誤觸蒙層拉到桌面最前景
await keyboard.type('hello') // 循序發送 'h' 'e' 'l' 'l' 'o' 五鍵
await sleep(1000) // 等待 1000ms
await keyboard.tab() // 發送 TAB 鍵
await keyboard.escape() // 發送 ESC 鍵
await keyboard.backspace() // 發送 BACK SPACE 鍵
await keyboard.enter() // 發送 ENTER 鍵
await keyboard.enable(false)
```
針對需要清除瀏覽器 session 資料(例如 cookie)的應用場景,可以使用 clearSessionData() 函式,需注意 clearSessionData() 是非同步函式
```javascript
// clear browser session data
return clearSessionData()
```
如果希望這段腳本在下一個步驟前重複被執行一次,可以使用 repeat() 函式,這個函式會在流程的下一個步驟前再插入這段執行腳本,可以在腳本中任何地方呼叫:
```javascript
// 如果在現在網頁中找到「下一頁」按鈕,就在5秒後重新執行腳本
let btn = document.querySelector('Button#nextPage')
if (btn) {
repeat(true, 5000)
// 0.5秒後才點擊下一頁,避免腳本內還有需要執行的工作
_.delay(() => btn.click(), 500)
}
// ...
```
腳本中也可以創建 MD5、SHA1、SHA256、SHA512 物件來計算 hash 值與 hmac 值:
```javascript
// 創建 MD5 物件
let md5 = createHash('MD5')
// 計算 MD5 hash 值,輸出 '5d41402abc4b2a76b9719d911017c592'
md5.hex('hello')
// 計算 salt 為 'key' 的 hmac 值,輸出 '04130747afca4d79e32e87cf2104f087'
md5.hex_hmac('key', 'hello')
```
非同步函式 setUserAgent(agentString) 可以針對會檢查瀏覽器型號的網站回報指定型號:
```javascript
// 設定成 Chrome Mac 版的型號
await setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.156 Safari/537.36")
```
###
列印輸出
將現在瀏覽器中的頁面輸出成 PDF 格式檔案或輸出到印表機。
###
等待數秒
告訴 EMILY 機器人在這個步驟等待指定的秒數後再繼續執行。
###
刪除步驟
刪除 EMILY 機器人紀錄學習的步驟。
###
保存內容
以滑鼠在瀏覽器頁面中選擇目標節點並擷取指定的內容種類並存成本機檔案。點擊到的節點會標識成紅色,使用者可以在 EMILY 主視窗以標準的 [CSS Selector](https://developer.mozilla.org/zh-TW/docs/Web/CSS/CSS_Selectors) 修正目標節點路徑。
選擇保存文字內容時,若選取節點路徑為 HTML Table 標籤時,將存檔名稱的副檔名命名為小寫 .csv 時 EMILY 機器人會自動將網頁中表格內容轉換成 CSV 格式。
###
發送按鍵
發送 ENTER、BACKSPACE、ESCAPE、TAB 四種按鍵(其他按鍵可以由**插入文字**或鍵盤直接輸入)。
###
等待節點
以滑鼠在瀏覽器頁面中選擇目標節點作為確認步驟並指定逾時秒數,在執行時期 EMILY 機器人會等到頁面出現選擇節點才繼續,否則以錯誤狀態結束,通常用在動態網頁的操作上。
###
引導用戶
以滑鼠在瀏覽器頁面中選擇目標節點並輸入提示文字,在執行時期 EMILY 機器人到了這個步驟會暫停自動執行,並以紅色標識節點,同時主視窗顯示提示文字來引導用戶接手操作頁面,完成後點擊**「完成了」**讓機器人繼續自動執行。
###
修改檔名
修改工作資料夾中的檔案名稱。來源檔案欄位可以夾帶 **%FILENAME%** 變數,執行時會以工作資料夾內檔名為 **FILENAME** 的 TXT 檔案內容取代,達到動態指定的效果。
###
工作資料夾
以 Windows 檔案總管或 Mac Finder 打開工作資料夾,可用來檢查目前執行暫存的資料。
---
# 資料安全指南
Source: https://docs.emily.tips/security
> EMILY.RPA 資料安全指南:工作資料夾的存取範圍、以使用者權限執行的意義,以及技能安裝時的路徑授權機制。
EMILY.RPA 作為代替使用者操作電腦流程的機器人,需要在作業系統登入後以使用者權限執行,因此對檔案或其他作業系統相關資源的權限也與使用者相同。為了確保技能在機器人執行時,存取的檔案沒有超過使用者預期,因此新的工作資料夾會在每一次技能執行時產生,作為存取資料的範圍。技能中的指令與模組可以直接存取工作資料夾中的檔案,但如果要存取在工作資料夾以外的檔案或資料夾,就需要在安裝技能時讓使用者指定該檔案或資料夾的路徑。


安裝時使用者自行指定的檔案或資料夾都會留在本機,供技能執行時需要的指令或模組參考,檔案內容並不會被上傳。
## EMILY.RPA 雲端的資料保存原則
### 帳號
帳號是使用 EMILY.RPA 的授權依據,用來驗證是否能合法執行授權的各項功能。帳號在雲端僅保存註冊的電子郵件信箱,用來發送動態隨機碼與驗證,毋需其他個資,驗證後只能從 EMILY.RPA 軟體執行各項功能。
### 技能
當使用者設計完一個技能,除了儲存在本機外,該技能會上傳到 EMILY.RPA 的雲端伺服器備份。技能的內容包`識別碼`、`名稱`、`說明`、`技能群組`與各項設定參數,以及流程操作指令。企業方案的群組管理後台會保存所有的上傳技能版本,否則只保存最新版本。而使用者執行技能時,每個指令都是在本機電腦執行,執行產生的檔案儲存在技能工作資料夾中,不會上傳雲端伺服器。

### 使用紀錄
使用 EMILY.RPA 軟體與執行技能的時間記錄會保存在雲端,供企業方案的群組管理後台稽核使用。這些使用存取紀錄會保存一年,過期資料會逐步銷毀。

## 技能的資料保護設計
EMILY.RPA 的設計工具有著高度的彈性,讓使用者可以依照自己的需求建構客製化的流程,因此在設計過程中需要對資料保護保持警覺,避免個資或機敏資料不小心於設計或執行技能時外洩。
### 隔離指令參數
EMILY.RPA 的「技能」主要是由流程操作步驟的序列構成,例如到 www.wikipedia.org 搜尋關鍵字然後下載搜尋結果並存成 PDF 檔這個簡單例子,就會是這些步驟的序列:「前往 wikipedia」、「載入 wikipedia」、「輸入關鍵字」、「按下 ENTER」、「載入搜尋結果頁」、「將結果存檔」、「匯出工作資料夾」。

以「前往網址」這個指令來說,技能中會紀錄「**前往網址**」這個指令與 `https://www.wikipedia.org/` 這個參數;又例如「**鍵盤輸入**」這個指令在技能中會紀錄「**鍵盤輸入**」這個指令與 `world wide web` 這個文字字串參數。因此當技能設計結束點擊「**上傳**」時,EMILY.RPA 會將這些指令與參數的序列傳送到使用者帳號的「**雲端技能庫 SKILL HUB**」備份起來,讓使用者未來可以下載與執行,而不必擔心本地軟體移除或電腦重灌造成「**技能**」遺失的問題,甚至可以讓使用者換一台電腦來執行技能。
我們以「**鍵盤輸入**」查詢關鍵字 `world wide web` 的例子來說,如果下次希望這個技能搜尋的關鍵字能改變,使用者可以利用「**調整**」技能的方式,在「**鍵盤輸入**」這個步驟修改文字參數:


這個方法雖然可以達到目的,但是免不了下次關鍵字又再修改時,又得重新調整並儲存一次,不僅缺乏彈性,而且關鍵字也隨著技能上傳。因此我們建議的方法是將關鍵字在本地端存成參數檔案,並讓 EMILY.RPA 在執行指令時才讀取檔案內容作為關鍵字。

這時上傳技能到「**雲端技能庫**」保存的會是檔案路徑而不是資料本身。
### 保護本機參數檔案
隔離指令參數成本機檔案後,雖然資料不會上傳雲端,但是參數檔仍然很容易暴露給可以存取這台電腦的其他人,因此 EMILY.RPA 提供加密功能,點擊「**帳號設定**」裡的「**保護資料**」,將要保護的關鍵字內容加密起來。


這樣在本機「**儲存**」成參數檔 keyword.txt 時,就會以這台電腦為 EMILY.RPA 提供的加密金鑰加密起來,只有 EMILY.RPA 可以在讀取時解密回原文。

### 自動化模組
自動化模組本身的參數包含 No-Code 的所有參數於 Low-Code 的腳本。以示範技能中的「匯出工作資料夾」這個模組來說,匯出目標資料夾路徑與無程式碼指令的參數都會隨技能上傳,因此 `FILTER` 也可以考慮採用 **%FILENAME%** 變數來隔離參數內容。

PowerShell 模組與命令列模組,由於這兩個模組會將腳本轉交作業系統的 PowerShell 與終端機命令列模式執行,因此無法由 EMILY.RPA 控管。對使用者而言,安裝技能時要特別留意。
## EMILY 公有雲資料傳輸安全
EMILY 公有雲([https://emily.tips](https://emily.tips))代管於 **Google Cloud Platform (GCP)**,由 GCP 提供機房實體安全、網路隔離與資料靜態加密(encryption at rest)等基礎防護。
在資料傳輸(in transit)方面,EMILY 公有雲一律以 **TLS 1.3** 加密,並支援 **後量子密鑰交換(post-quantum key exchange)** 機制 `X25519MLKEM768`。這是 X25519 橢圓曲線與 NIST 標準化的 ML-KEM-768(Kyber)所組成的混合式密鑰交換:即使未來量子電腦具備破解傳統橢圓曲線的能力,今日側錄的加密流量也無法在事後被解密,可有效防範「先竊取、後解密」(harvest now, decrypt later)的攻擊手法。
### 自行驗證加密機制
使用者可以在本機以 `openssl` 指令驗證 EMILY 公有雲的傳輸加密設定(需要 OpenSSL 3.5 以上版本才支援 `X25519MLKEM768`):
```bash
openssl s_client -groups X25519MLKEM768 -alpn h2,http/1.1 \
-connect emily.tips:443 -servername emily.tips &1 \
| grep -i "Negotiated TLS1.3 group\|Protocol\|ALPN"
```
正常情況下會得到以下結果:
```text
Negotiated TLS1.3 group: X25519MLKEM768
Protocol: TLSv1.3
ALPN protocol: h2
```
三行輸出分別代表:密鑰交換使用後量子混合演算法、連線協定為 TLS 1.3、應用層協定協商為 HTTP/2。
## 弱點掃描與分析
EMILY.RPA 委由 **動力安全資訊股份有限公司(Dynasafe Technologies Inc.)** 於其研發環境所建置的資安弱點測試平台,進行第三方弱點掃描與安全分析。動力安全的安全檢測人員依 EMILY.RPA 的作業需求先行建立測試系統環境,並依標準安裝程序完成部署後,才啟動全面性弱點掃描,並對安裝前後的結果進行比對與綜合分析。
### 分析結果
經資安顧問綜合分析後確認:
- 系統整體未發現可被利用的安全漏洞或弱點。
- 未開放外部未授權連線或服務埠。
- 作業系統防護機制(防火牆、服務權限、網路隔離等)運作正常。
報告結論指出,安裝 EMILY.RPA 後未新增任何高風險或可被利用的安全弱點,未發現與 EMILY.RPA 相關之安全弱點或潛在風險,整體環境運行穩定且安全可靠。
### 報告下載
EMILY.RPA 弱點掃描分析報告(PDF,2026-08-06)
---
# 版本發佈記錄
Source: https://docs.emily.tips/versions
> EMILY.RPA 各版本的發佈記錄與更新內容說明。
EMILY.RPA 版本發佈記錄與內容說明
### 4.2.20261018
* 新功能:AI Agent 模組支援 vLLM/Llama.cpp 地端模型
* 功能改進:Agentic Workflow 當無法達成任務時回覆 MISSION ABORT
* 功能改進:Comupter Use 支援多指令執行
* 新功能:Mac 版本新增區域網路權限
* 功能改進:Browser Use 讀取網頁逾時延長至 30 秒
* 修正問題:Web Automation 非最上層瀏覽器在遇到網頁自動載入時應忽略指令觸發
* 新功能:紀錄檔加入 EMILY 網域憑證資訊與 Proxy 模式
### 4.2.20260910
* 新功能:個資遮蔽模組(PII Redaction)
* 新功能:AI Agent 模組支援 Ollama Qwen3.8/Gemma4 地端模型
* 功能改進:檔案觸發時寫入觸發的檔案路徑到工作資料夾 file-path.txt
* 功能改進:啟動應用程式時加入 --debug-log 參數啟動週期性除錯紀錄
* 功能改進:工作資料夾 config.json 支援 subframeShim 開關
* 功能改進:模組中檔案存取透過模組進程讀寫
### 4.2.20260826
* 新功能:遠端桌面自動化
* 修正問題:因應 Exchange Online Server 傳送 IMAP 延伸規格 LOGINDISABLED
### 4.1.20260809
* 功能改進:SQL執行分析模組 MSSQL 逾時設定延長
* 修正問題:Browser Use Agent 在開啟多個瀏覽器視窗後可能造成後續指令錯誤
* 修正問題:Chromium v146 對特定下載行為會發出網頁重載信號導致下載失敗
* 修正問題:Chromium v146 對執行瀏覽器視窗蒙層禁止半透明
* 修正問題:PDF表格分析模組在啟動後第一次在訓練模式載入小檔案有機率失敗
* 修正問題:網頁腳本內使用 repeat() 失效
* 修正問題:Agentic Workflow / Browser Use 模組在點擊會啟動 PDF 預覽時會無法繼續控制瀏覽器
### 4.1.20260723
* 新功能:新增遠端觸發 (Remote Trigger) 與 Agentic Workflow 遠端技能 (Remote Skill)
* 功能改進:Windows 所有執行檔憑證簽章
* 修正問題:減少 V8 IPC 數量以降低 V8 Engine 模板數達上限
### 4.0.20260614
* 功能改進:模組寫入 execute.log 時間戳記改為本地時間
* 功能改進:main.log 紀錄使用者關閉 app
* 修正問題:網頁自動化目標網站採開新視窗下載非 PDF 檔案偵測失效
### 4.0.20260605
* 新功能:新增 Agentic Workflow 模組
* 新功能:新增 Llama.cpp 模組
* 新功能:桌面自動化模組支援 Windows on ARM
### 3.9.20260408
* 新功能:Agent 模組支援 Claude 系列模型
* 新功能:Agent 模組測試執行會在除錯中控台列印 token 使用成本(適用所有版本)
* 新功能:桌面自動化模組支援 desktopUse(goal, options) API
* 新功能:新版英文線上文件發佈
### 3.9.20260326
* 新功能:使用者可以從訓練模式匯入技能
* 功能改進:網頁執行腳本編輯視窗改為主界面的子視窗
* 功能改進:新版設計首頁的網址列提供模組關鍵字搜尋
* 功能改進:AI Agent 模組支援 AskEMILY
* 新功能:Web Read Agent 支援目前瀏覽器內網頁讀取
### 3.8.20260313
* 功能改進:自動化模組執行無程式碼指令與錯誤訊息合併寫入 execute.log
* 功能改進:自動化模組 Ask EMILY 升級語言模型與新增提交、測試工具
* 功能改進:Excel 表格處理與 Excel 表格分析模組在帶入表格資料會自動忽略表頭列
* 修正問題:工作資料夾執行腳本模組呼叫子技能沒有作用
### 3.8.20260228
* 新功能:新繁體中文線上文件 https://doc.emily.tips
* 新功能:系統選單新增客戶支援入口
* 新功能:帳號詳情頁新增技術服務入口
* 新功能:多電腦授權帳號在全自動觸發模式提供多工執行,啟動時其他電腦無法進入全自動觸發模式
* 功能改進:主界面所有對話框的渲染效能改進
* 功能改進:刪除技能增加使用者確認
### 3.8.20260123
* 功能改進:啟動排程時檢查並排除錯誤排程
* 功能改進:排程過時強制觸發,並紀錄排程設定
* 修正問題:年度排程被排程器拒絕
* 功能改進:模組視窗移除拼音檢查提示
* 功能改進:訓練模式初始設定對話框的按鍵監聽只對 ENTER
* 修正問題:循環中連續下載逾時第二次無效
* 修正問題:郵件觸發時郵件的附件無名稱會中止觸發
### 3.8.20260108
* 新功能:帳號設定新增「啟動時進入觸發器模式」
* 新功能:新增 AI Token 儲值無餘額通知
* 新功能:技能設定頁新增「輸入/輸出說明」
* 修正問題:「下載」指令逾時在特定下載觸發方式無法解除
* 功能改進:瀏覽器相容 Cloudflare Turnstile
### 3.8.20251208
* 新功能:Agent 模組新增 Gemini-3 Pro 模型
* 修正問題:郵件觸發綁定郵箱後在設定介面仍然顯示未綁定
### 3.8.20251109
* 新功能:新增全自動觸發模式與觸發工作佇列,降低使用者干擾與提高穩定性,並增加資源監控紀錄
* 新功能:新增網頁觸發,支援同網段上多人從遠端觸發技能
* 新功能:新增系統可用記憶體監控,當低於 2GB 提示
* 新功能:Agent 模組新增 GPT5 系列模型
* 新功能:BrowserUseAgent 模組新增 OpenAI/Gemini Computer-Use 模型
* 新功能:群組後台管理員可將群組使用者踢出
* 功能改進:安裝程式預設啟動 Web Security 設定
* 功能改進:安裝程式支援日文
* 功能改進:教練模式可匯入轉移技能
* 修正問題:Skill Hub 版本歷史列表框線不明顯
* Chromium 版本更新至 140.0.7339.249
### 3.7.20251007
* 新功能:技能在調整模式下可多選步驟然後刪除、標示跳過、存成新技能
* 功能改進:在執行模式工作資料夾 config.json 支援 highlight: true/false 開關
* 功能改進:Agent模組在語言模型輸出格式不正確時嘗試自動修復
* 功能改進:啟用授權時根據帳號授權數自動轉換授權檔的期限
* Chromium 版本更新至 138.0.7204.252
### 3.6.20250918
* 新功能:AskEMILY 啟用模型零資料保存ZDR功能
* 新功能:Agent 模組支援群組 %credit-key%,並啟用模型零資料保存ZDR功能
* 新功能:群組後台新增 Credit History,Log 增加模型 Token 價格
* 功能改進:Mail Trigger 附件檔案沒有檔名就自動產生
### 3.6.20250904
* 新功能:Web Automation 下載指令新增逾時參數
* 功能改進:郵件觸發附件檔名合規轉換
* 修正問題:Web Automation 自定義函式庫與特定網站 Google Analytics 衝突
* 新功能:落地自建 Server 提供管理員設定單一帳號授權數
### 3.6.20250821
* 新功能:AskEMILY 與 Agent 模組加入稽核紀錄
* 修正問題:循環中載入頁面指令逾時行為應依循循環中指令失敗設定
* Chromium 版本更新至 136.0.7103.177
### 3.6.20250808
* 新功能:EMILY Server 管理頁面支援手機螢幕
* 新功能:Desktop Automation 模組支援 desktopUse() API
* 功能改進:Browser Use Agent 模組目標欄位支援%VAR%樣板
* 修正問題:技能逾時應關閉模組視窗
### 3.6.20250717
* 新功能:Table Write Agent 模組
* 新功能:File System Agent 模組
* 功能改進:Browser Use Agent 模組支援 iframe
* 功能改進:Web 執行腳本常用函式庫 moment.js / lodash.js 改進與網頁的命名衝突
* 功能改進:載入網頁指令支援逾時參數
* 功能改進:PDF表單分析模組訓練模式提供換頁選單
* 功能改進:呼叫子技能發生錯誤時提供 error-\{uuid.timestamp\}.txt log
* 修正問題:Table Read Agent 模組讀取 .tsv 檔會失敗
### 3.5.20250620
* 新功能:Document Read Agent 模組支援 DOCX / Google Docs / TXT
* 新功能:Table Read Agent 模組
* 修正問題:Web 執行腳本 repeat() API 在腳本中觸發新頁面時失效
* 修正問題:訓練模式下部分網站與瀏覽器內部符號 mode 衝突
* 修正問題:Web Automation 插入文字指令與 type() API 在跨域 iframe 中失效
* 修正問題:Browser Use Agent 自動選擇網頁中選項多次時失敗
### 3.5.20250607
* 新功能:預設帳號與群組共用密碼
* 新功能:Skill Hub 支援封存技能
* 新功能:Google Drive 模組新增 moveto(folderID) API
* 功能改進:SFTP 模組會忽略 FTP/TLS 伺服器憑證錯誤
* 功能改進:群組後台稽核紀錄CSV下載新增PCID欄位
* 修正問題:Web Automation 執行時由腳本觸發事件的下載會造成技能停止
* 修正問題:Web 執行腳本 repeat() API 沒有作用
### 3.5.20250527
* 修正問題:執行模式下保存內容指令截屏會找不到目標節點
### 3.5.20250525
* 新功能:Browser Use Agent 模組
* 新功能:單一授權帳號開放線上購買短期授權
* 新功能:教練模式 Skill Hub 新增技能匯出功能與落地帳號匯入
* 新功能:Web Automation 支援 preload.js
* 功能改進:網頁腳本在訓練模式進入程式碼編輯器時恢復正常滑鼠行為,離開時恢復為選擇節點
* 功能改進:保存內容在訓練模式,使用者更改節點路徑完成後將新路徑節點設為高亮
* 修正問題:解決 Web Automation 內建 sleep / selectNode API 衝突
* 修正問題:執行模式下 script 與 wap 指令改二階段驗證
* Chromium 版本更新至 134.0.6998.205
### 3.3.20250425
* 新功能:Web Read Agent 模組
* 新功能:Document Read Agent 模組
* 新功能:ECPay 金流正式環境
* 修正問題:Mac Desktop Automation 滑鼠座標與螢幕解析度不同步
* 修正問題:調整主技能時,加入子技能展開,修改子技能步驟,原始子技能也會被修改
### 3.3.20250411
* 新功能:版本資訊詳情頁加入語言選項
* 新功能:支援 Windows AD SSO
* 新功能:Web Script 支援 record API 錄製瀏覽器內容,輸出 webm 格式檔案
* 新功能:工作資料夾 config.json 支援 partition 以指定獨立瀏覽器子技能的技能群組
* 功能改進:更新 Low-Code 編輯器,提示懸浮視窗可以連往 MDN 文件
* 新功能:Gemini WAP 支援 webm 檔案提示
* 功能改進:execute.log 增加指令提示與子技能呼叫關係
* 修正問題:Web Script Ask EMILY 在清除對話後會忘記網頁內容
* 修正問題:工作資料夾 config.json ignoreHide 在網頁彈出的子瀏覽器視窗失效
* 功能改進:針對小尺寸螢幕進入訓練模式不超出螢幕寬度
* 新功能:測試 ECPay 金流與電子發票串接
* 修正問題:線上購買授權後應立即加入授權列表
### 3.3.20250322
* 新功能:模組 API api.files(ignoreDefault) 提供參數,可忽略過濾執行紀錄檔與錯誤紀錄檔
* 新功能:Desktop Automaion 模組新增 api.cwd() 可取得目前工作資料夾的完整路徑
* 新功能:Mail Reader 與 Exchange Mail Reader 模組新增 api.mail.moveto() 與 api.mail.remove()
* 功能改進:新增 UI 瀏覽器 crash 的自動回復
* 功能改進:帳號詳情分類
* 新功能:測試 ECPay 金流串接
* 功能改進:技能數量大時主畫面中我的技能展示效率優化
* 功能改進:Web Automation 錄製巢狀 iframe 時加上舊版演算法的 fallback
* Chromium 版本更新至 130.0.6723.191
### 3.2.20250309
* 新功能:Web Automation No-Code 錄製支援瀏覽器API showOpenFilePicker/showSaveFilePicker, 可用工作資料夾 config.json \{ "pickfile": true/false \} 開關
* 新功能:Web Automation 瀏覽器支援工作資料夾 config.json \{ "screen": \{ "width": 480, "height": 800 \} \} 設定瀏覽器螢幕參數
* 新功能:ChatGPT/Gemini 模組上傳影像檔支援複數檔案 \["file1.jpg", "file2.png"]
* 功能改進:Desktop Automation 滑鼠鍵盤底層函式庫優化
### 3.2.20250220
* 功能改進:執行結果頁面調整呈現方式,快取執行結果以降低對硬碟存取次數
* 功能改進:Web Automation 執行腳本 Ask EMILY 調整呈現方式,記住對話,並提供 TEST 功能
* 功能改進:Web Automation 執行腳本手動調整目標節點路徑後(按TAB或點擊其他元件)瀏覽器會標示節點
* 新功能:Web Automation 執行腳本可切換「點擊選取目標節點」
* 功能改進:模組 Code.AI 功能升級為對話式的 Ask EMILY
### 3.2.20250209
* 新功能:訓練模式首頁AI輔助改名爲 Ask EMILY,以對話方式提供建議,除依照使用者需求建議模組之外,也包括可使用技能的建議(技能需提供說明)
* 新功能:Web Automation 執行腳本加入 Ask EMILY,可針對使用者提示與點選網頁目標節點生成 Low-Code
* 新功能:Web Automation 執行腳本支援 Clipboard API
* 新功能:Web Automation config.json 支援 ignoreHide true/false 屬性,對執行模式瀏覽器忽略隱藏視窗的請求,例如呼叫 Desktop Automation 模組時
* 新功能:Excel填值模組支援 formula() API
* 新功能:PowerShell模組支援 No-Code 指令 Copy Excel Sheet 與 Export Excel to PDF
* 功能改進:執行模式 Web Automation 保存內容指令使用截屏前強迫瀏覽器更新
* 功能改進:技能指令列表中,子技能顯示名稱 - 識別碼
* 修正問題:訓練模式中 Web Automation 執行腳本中,測試腳本發生錯誤時目標節點選取會失效
* 修正問題:訓練模式中 EXCEL表格處理/分析模組在 Sheet 欄位填入後立即按儲存,該欄位不會更新
### 3.2.20250120
* 修正問題:訓練模式錄製上傳指令時失敗,由於 Chromium 128.0.6613.186 改變選取檔案後的路徑取得方式
### 3.2.20250119
* 新功能:新增全背景執行模式、系統匣圖示、系統匣選單,包括開啟/關閉視窗、檢查更新、打開紀錄檔、重新啟動、退出
* 新功能:雲端管理後台支援備份技能版本、自訂系統通知信
* 新功能:Skill Hub 支援關鍵字搜尋技能
* 修正問題:執行模式中主技能設定逾時,逾時發生時一併結束獨立瀏覽器視窗執行的子技能
* Chromium 版本更新至 128.0.6613.186
### 3.1.20250103
* 功能改進:Desktop Automation 報錯標題 template-not-found 改為 target-not-found
* 功能改進:執行模式中 Web Automation 在 ignoreNavigate 設定作用後,如果沒有在執行狀態則恢復執行
### 3.1.20241220
* 新功能:Web Automation config.json 支援 ignoreNavigate 參數,若瀏覽器前往的網址包含參數字串將被忽略
* 功能改進:延長郵件觸發的等待逾時從15秒到60秒
* 修正問題:訓練模式首頁 Web Automation 網址列 %VAR% 變數應該記錄在指令中
### 3.1.20241128
* 新功能:執行結果頁增加 main.log 入口
* 新功能:帳號設定頁增加線上文件入口
* 新功能:群組管理後台提供管理員密碼重設與使用者註冊客製郵件範本
* 修正問題:Web Automation 應紀錄 JS alert() 內容
* 修正問題:訓練模式 Web Automation 網址列應支援 %VAR% 文檔變數
* 功能改進:執行模式 execute.log 不需自動換檔
* 功能改進:郵件觸發 keep alive 回應時間過久自動重新連線
### 3.1.20241101
* 新功能:新模組 PDF轉存影像 (pdf2img)
* 新功能:模組提示增加日文
* 修正問題:Web Automation 訓練與執行模式 config.json 中 ignoreClose / confirm 涵蓋範圍
* 修正問題:Web Automation repeat() 預設應等同 repeat(true)
* 修正問題:Web Automation 載入特定網頁與 lodash.js 衝突
* 功能改進:模組 api.read(filename, encoding) 預設讀回 buffer, txt/csv/json 預設讀回 UTF-8 字串, 並可指定 encoding 'utf8', 'hex', 'base64'
* 功能改進:Web Automation iframe 定位加上 id / name 屬性
### 3.1.20241022
* 修正問題:訓練模式下使用循環表格工作,進入循環時無法分離逗號分隔的資料列
### 3.1.20241018
* 新功能:訓練模式新首頁,提供模組說明,快搜,以及Process.AI
* 新功能:新增日文使用者介面
* 功能改進:郵件觸發加入定時主動查詢新信件
* 功能改進:訓練模式所有模組支援本機語言的介面提示
* 功能改進:訓練模式所有Low-Code模組支援Code.AI與預設問題集
* 修正問題:Web Automation瀏覽器對特定網站 moment.js 函式庫會載入失敗
* 修正問題:Web Automation瀏覽器對特定網站下載功能失效
### 3.1.20240926
* 功能改進:Desktop Automation 模組執行時自動縮小瀏覽器視窗
* 功能改進:與 Server 的 session 被中斷後在主視窗頭像顯示斷線圖示
* 功能改進:安裝授權後更新授權數量
* 功能改進:訓練模式 Web Script 在跨域 iframe 頁面允許修改 iframe 定位屬性
* 新功能:群組管理後台提供匯出使用者授權檔
* 新功能:群組管理後台新增授權列表
* 修正問題:Ollama 模組應允許存取本地端點
* Chromium 版本更新至 126.0.6478.234
### 3.0.20240915
* 功能改進:模組採用獨立瀏覽器視窗
* 新功能:帳戶設定新增「啟用模組加速記憶體」,加速重複使用相同模組的載入速度
* 新功能:設定中點擊版本提供下載回復版本
* 功能改進:Web Automation 瀏覽器提昇安全機制,支援如 Google Form 等要求高網站
* Chromium 版本更新至 124.0.6367.243
### 2.9.20240727
* 新功能:讀取EXCHANE郵件模組提供 No-Code Command
* 新功能:EXCEL表格處理模組提供 No-Code Command
* 新功能:EXCEL表格分析模組提供 No-Code Command
* 新功能:資料夾管理模組提供 No-Code Command
* 新功能:GoogleDrive模組提供 No-Code Command
* 新功能:文件樣版套用模組提供 No-Code Command
* 新功能:SQL執行分析模組提供 No-Code Command
* 新功能:SFTP模組提供 No-Code Command
* 新功能:HTTP API執行分析模組提供 No-Code Command
* 功能改進:訓練模式與執行模式瀏覽器載入模組速度優化
* 功能改進:工作資料夾執行模組 No-Code Command 新增 Unzip All
* 功能改進:群組後台新增帳號授權數量欄位
* 修正問題:技能庫分享技能後排列順序錯誤
### 2.9.20240710
* 新功能:工作資料夾執行腳本模組提供 No-Code Command
* 新功能:匯出工作資料夾模組提供 No-Code Command
* 新功能:建立檔案列表模組提供 No-Code Command
* 新功能:EXCEL填值模組提供 No-Code Command
* 新功能:CSV表格建立模組提供 No-Code Command
* 新功能:讀取電子郵件模組提供 No-Code Command
* 新功能:GoogleSheet模組提供 No-Code Command
### 2.9.20240627
* 新功能:新增 Gemini 模組
* 新功能:PowerShell 模組新增 No-Code Command
* 新功能:Web 執行腳本與工作資料夾執行腳本支援 createHash() API
* 修正問題:SFTP 模組執行失敗不會產生例外
### 2.9.20240614
* 新功能:工作資料夾執行腳本、EXCEL表格處理、PowerShell 模組 Code.AI 提供常用問題集
* 新功能:新增 EXCEL 填入模組
* 功能改進:保存內容指令支援 csv / md 副檔名
* Chromium 版本更新至 122.0.6261.156
### 2.8.20240523
* 新功能:手動觸發執行技能即時指令列顯示包含新瀏覽器子技能與腳本呼叫子技能
* 新功能:Anti-Captcha 模組 API KEY 支援文檔變數 %VAR%
* 功能改進:ChatGPT 模組支援影像檔與輸出JSON格式
* 功能改進:發送 HTTP 請求模組採用瀏覽器核心 fetch API
* 修正問題:工作資料夾執行腳本模組在 Web-Security 開啟時 OCR 功能失效
### 2.8.20240514
* 新功能:新增 Google Object Detect 模組
* 新功能:訓練模式提供登入工具
* 新功能:Desktop Automation 執行時提供 Shift+ESC 結束執行
* 功能改進:簡化網站轉換頁面
* 功能改進:Code.AI 更新 LLM 至 OpenAI GPT-4o
### 2.8.20240401
* 功能改進:Web Automation 保持內容指令支援 iframe 內截屏
* 新功能:帳號設定提供 Web Security 開關
* 新功能:Web Automation 支援執行腳本中修改進階參數 config.json
* 新功能:Desktop Automation 支援低階滑鼠按鍵功能 api.mouse.press(), api.mouse.release()
### 2.8.20240315
* 新功能:SKILL HUB中技能更新指示
* 新功能:授權支援同帳號多電腦運行與技能訂閱
* 新功能:Windows 安裝支援 ARM64 裝置
* 功能改進:帳號設定頁面顯示授權數量
### 2.8.20240301
* 新功能:Web Automation 支援尋找圖案指令
* 新功能:關閉 App 或登出帳號前需使用者確認
* 新功能:執行結果管理選項提供保存 7 天與保存 14 天選項
* 新功能:帳號註冊提供落地版 server 端點輸入
* 功能改進:execute.log 紀錄 App 版本資訊
* 功能改進:App 更新詳情依語言提供連結
* 功能改進:Web Automation 執行腳本在訓練模式提供 debugger console 例外紀錄
* Chromium 版本更新至 120.0.6099.291
### 2.8.20240216
* 修正問題:桌面自動化 OCR 因瀏覽器核心模組搜尋行為改變導致失效
* Chromium 版本更新至 120.0.6099.283
### 2.8.20240203
* 新功能:技能庫技能作者如果允許使用者修改,共用的技能可供使用者複製
* 功能改進:使用者填入問題與答案輸入區顏色區隔
* 功能改進:桌面自動化 api.clickCrop / api.moveToCrop 提供滑鼠游標 instant 選項
* 功能改進:桌面自動化執行模式 Low-Code 發生例外紀錄腳本行數於 execute.log
* 功能改進:桌面自動化 api.debug 提供除錯錄影檔
* 功能改進:郵件觸發定期聯繫郵件伺服器(某些MSP伺服器會自行停止通知新郵件)
* Chromium 版本更新至 120.0.6099.268
### 2.7.20240112
* 修正問題:Web Automation 對會開啟三層以上瀏覽器子視窗的網頁在技能結束時會無法關閉
* 修正問題:循環工作中兩層以上巢狀子技能,並設定循環中錯誤繼續循環,在最內側造成例外後的下一個循環會造成循環狀態不同步
* 功能改進:子技能指令當設定為「使用新瀏覽器執行子技能」將顯示標識圖示
### 2.7.20240105
* 功能改進:訓練與執行模式結束時主動關閉瀏覽器子視窗
* 功能改進:訓練技能結束時預設保留 session cookies
* 功能改進:訓練模式加入子技能選擇新瀏覽器視窗將主動執行子技能
* 修正問題:Web Automation 尋找文字指令在特地邊界條件下會不斷重複尋找
* 修正問題:下載技能時指定參數檔給不正確檔案路徑後,設定無法還原原始狀態
* 新功能:提供認證考試模式 runtime
### 2.7.20231222
* 新功能:桌面自動化 mouse API 支援中間鍵
* 新功能:雲端技能庫支援 「匯出 Low-Code」
* 新功能:工作資料夾執行腳本模組 zip API 支援指定檔名編碼
* 新功能:帳號設定/匯入授權支援預覽授權檔內容
* 新功能:工作資料夾執行腳本模組支援 pdf API
* 功能改進:main.log 與 execute.log 調整
* 修正問題:調整技能模式,WAP 模組修改儲存後在技能存檔前沒有反應修改內容
### 2.7.20231208
* 新功能:存成PDF指令支援顯示頁首頁尾
* 修正問題:桌面自動化指令失敗不會拋出例外
* Chromium 版本更新至 118.0.5993.159
### 2.6.20231119
* 修正問題:工作資料夾執行腳本 zip API 在解壓縮密碼保護的檔案時若工作資料夾檔案已存在 api 會無法返回
* 修正問題:手動觸發執行技能時指令列表會出現刪除指令圖示
* 修正問題:訓練模式下,完成使用尋找文字指令後橘色標定沒有取消
* 修正問題:GoogleSheet 模組連續頻繁呼叫 API 會出現例外紀錄
* 修正問題:Web Automation **插入文字**指令1027採用模擬鍵盤訊號後造成心情符號變成亂碼
### 2.6.20231027
* 功能改進:Web Automation 中**插入文字**、**發送按鍵**、**mouse API**、**keyboard API** 支援 cross-site iframe;其中 mouse/keyboard API 新版本中無需佔用滑鼠與鍵盤裝置
* 功能改進:HTTP Analyzer 模組的 input 物件提供 headers 物件
* 新功能:Web Automation 支援**尋找文字**指令
* 新功能:Web Automation 執行腳本、工作資料夾執行腳本模組、Desktop Automation 模組的 offline ocr API 新增繁體中文模型
* 新功能:Installer 安裝程式在自動更新失敗後提供手動下載
### 2.6.20231012
* 新功能:新增 Job Forwarder 模組,支援多機器人自動化分工
* 新功能:安裝與執行技能可選擇目標機器人
* 修正問題:cross-site iframe 無法偵測與執行腳本,以及與 JQuery 衝突問題
* 修正問題:網站 host 在 cloudflare CDN 瀏覽器檢查頁反覆載入
* Chromium 版本更新至 116.0.5845.228
### 2.5.20230917
* 功能改進:EXCEL表格處理模組與EXCEL輸出模組支援舊格式 XLS 輸出,但EXCEL輸出模組的樣式無法支援 XLS 格式
* 功能改進:Web Automation 中網頁使用瀏覽器Alert/Confirm彈窗時在工作資料夾輸出彈窗中訊息
* 功能改進:Web Automation 上傳指令步驟提供**主動發送事件**選項,預設勾選與舊版本行為相同
* 功能改進:Low-Code 編輯器可隨瀏覽器視窗縮放
* 功能改進:SFTP 模組支援更多加密演算法
* 新功能:教練模式技能庫支援 ZIP 技能內 Low-Code
* 修正問題:DA 模組 No-Code 訓練介面在 Windows 上顯示設定調整放大比例為非 100% 會造成 Crop 定位顯示位移
### 2.5.20230901
* 新功能:SQL Executor 模組 USER、PASSWORD、DATABASE 欄位支援 %VAR% 文檔變數
* 功能改進:作業系統地區設定 CN 將提供繁中版介面
* 功能改進:Web Automation 偵測暴力彈窗瞬間開關行為並忽略
* 修正問題:Web Automation 執行模式目標節點 highlight 方式有機會造成部份網站 crash
### 2.5.20230826
* 新功能:新增 JSON API Server 模組
* 新功能:新增 File Web Server 模組
* 功能改進:訓練模式右鍵選單新增 Inspect Node 與 Monitor DOM 功能,可對腳本建立 DOM 的子視窗進行 No-Code 步驟錄製
* 功能改進:模組步驟可忽略 Navigate / Load 指令,簡化流程
* 功能改進:HTTP Analyzer 模組 Form 參數欄位支援 %VAR% 文檔變數
* 功能改進:Web Automation 瀏覽器視窗 crash 時自動重載
* 修正問題:Desktop Automation 調整時仍然使用舊版模組介面
### 2.5.20230811
* 新功能:Google Sheet 模組支援批次讀寫 API
* 新功能:教練模式 Skill Hub 提供複雜度試算與明細下載
* 新功能:全自動觸發失敗以郵件通知使用者
* 功能改進:Google Sheet 模組讀寫儲存格減少 Google API 使用
* 功能改進:Desktop Automation 模組新增 crop 檔案快取機制,縮短執行準備時間
* 功能改進:執行模式的載入與下載狀態改以蒙層狀態列顯示,減少因彈窗造成的系統資源使用
* 功能改進:Web Automation 支援腳本建立 DOM 的子視窗
* 修正問題:循環工作內設定條件執行子技能,如果子技能失敗過後續循環條件會失效
* Chromium 版本更新至 114.0.5735.289
### 2.5.20230728
* 新功能:Web Automation 執行腳本支援 keyboard API
* 新功能:擴展帳號下載安裝技能選單
* 新功能:擴展帳號手動觸發技能選單
* 功能改進:排程觸發欄位支援一次指定多個時間
* 功能改進:優化儲存技能時間
* 修正問題:Web Automation 執行腳本若錄製時沒有指定節點路徑,調整時將無法加入
* 修正問題:PDF 表單分析模組在第二頁以後滑鼠選取區域自動產生的位置參數與頁碼衝突
* Chromium 版本更新至 114.0.5735.248
### 2.5.20230716
* 新功能:帳號擴展機制
* 新功能:在線/離線時指示(最晚5分鐘更新)
* 新功能:訓練模式在 Web Automation 按右鍵可保存離線網頁 MHTML 格式
* 新功能:訓練模式在 Web Automation 按右鍵可在 Debugger 列出節點族譜
* 功能改進:Debugger 提供 dock 選項
* 功能改進:Code.AI migrate to GPT-4
* 修正問題:執行模式下載檔案無檔案類型資訊時改以提示檔案名稱解析副檔名
* 修正問題:執行模式定位節點時標示方法優化
* 修正問題:執行模式**保存內容**指令為截屏時確保循序截屏
* 修正問題:執行模式**捲動縮放**指令改成立即生效
* 修正問題:Web Automation 執行失敗保存離線網頁改成 MHTML 格式
* Chromium 版本更新至 114.0.5735.199
### 2.4.20230631
* 新功能:技能執行失敗時如果失敗在 Web Automation,工作資料夾將保存失敗網頁 error.html
* 新功能:Google Drive 模組,資料夾物件提供建立子資料夾 createFolder 函式
* 新功能:管理後台提供使用者活動紀錄下載
* 功能改進:上傳技能後 Skill Hub 提供該技能複雜度的參考值
* 修正問題:避免保存內容指令產生無效下載
* 修正問題:更新新版 Chromium 核心後瀏覽器視窗被遮擋會暫停渲染與執行網頁
* 修正問題:前往網址在前一個網頁如果還在載入中並有資源載入錯誤時,不應該中斷前往新網址
### 2.4.20230611
* 新功能:**帳號設定**增加匯入授權檔功能,授權檔可以指定帳號延長期限、帳號群組、可下載技能
* 新功能:Mac版本發佈加入 Apple Nortarization 程序,安裝不會被**隱私與安全**阻擋
* 修正問題:**郵件觸發**斷線不會重連
* 修正問題:**EXCEL表格處理**模組指定表頭欄位,在輸出格式為 XLSX 時其他欄位依然存在
* 修正問題:郵件觸發 Exchange Online 設定完成不會顯示結果
* 修正問題:SQL執行分析寫入資料 Oracle 資料庫不會 commit
### 2.4.20230527
* 新功能:**郵件觸發**新增 Exchange Online 支援
* 新功能:**桌面自動化**模組新增 api.mouse.doubleClick, api.mouse.getPosition 函式
* 修正問題:**桌面自動化**模組 api.pasteText 寫入剪貼簿與貼上之間需等待
* 修正問題:SQL Executor 模組無法載入 MSSQL 驅動程式
* 修正問題:**網頁自動化**模組如果**前往網址**的指令為下載連結,下載完不會繼續流程執行
* Chromium 版本更新至 112.0.5615.204
### 2.4.20230514
* 新功能:新增發送 Exchange 郵件模組
* 新功能:新增讀取 Exchange 郵件模組
* 修正問題:DA Low-Code 存取權限
* 修正問題:DA api.pasteText, api.ctrlA, api.ctrlC, api.ctrlV 等待時間不足
* Chromium 版本更新至 112.0.5615.165
### 2.3.20230427
* 新功能:SFTP 模組新增 api.ftp.rename 與 api.ftp.remove
* 新功能:DA 模組新增 api.powerShell 與 api.run
* 新功能:Google Drive 模組的資料夾物件新增 createSpreadsheet 函式
* 新功能:新增 SSH 模組,支援遠程終端 ssh 與 telnet
* 修正問題:主界面在執行技能時畫面更新會遲滯
### 2.3.20230407
* 新功能:Web 執行腳本,DA 桌面自動化,以及其他需要 Low-Code 的 Edge Processor 模組提供 API 自動提示
* 新功能:Edge Processor 需要 Low-Code 的模組提供 Code.AI 功能
* 修正問題:「循環工作」設定「選用執行」循環來源檔不存在依然停止執行並且報錯
* 修正問題:「插入子技能」設定「條件執行」後子技能中指令的「條件執行」失效
* 修正問題:從包含 iframe 的主頁直接「前往網址」到 iframe 網頁會造成 render-process-gone
* Chromium 版本更新至110.0.5481.208
### 2.3.20230322
* 新功能:Low-Code 模組新增 Code.AI 自然語言腳本幫手
* 新功能:新增 ChatGPT 模組
* 修正問題:DA 原瀏覽器 Trainer UI 因瀏覽器安全政策無法正常運作
* Chromium 版本更新至110.0.5481.192
### 2.3.20230312
* 新功能:新增 Edge Processor **QR Code** 模組
* 新功能:**工作資料夾執行腳本**新增 api.writeXML
* 功能改進:工作資料夾 execute.log 增加紀錄 CPU 負載與可用記憶體
* 修正問題:Workaround Chromium 在載入 main page 時同步載入 multiple iframe 造成 crash
* Chromium 版本更新至110.0.5481.179
### 2.2.20230225
* 新功能:**PowerShell** 模組支援文檔變數 %VAR%
* 新功能:**EXCEL輸出** 模組支援設定欄寬與列高
* 新功能:技能指令列支援**指令提示**功能
* 修正問題:**工作資料夾執行腳本** api.splitCSV 當整數切分來源 CSV 檔案時會多產生最後一個切分檔
* 修正問題:**桌面自動化** DA 模組指令名稱 WAITFOR 錯字
### 2.2.20230211
* 新功能:新增 Cloud Processor [**Azure Form Recognizer**](./wap/azureformrecognizer.md) 模組
* 新功能:Web Automation 新增**列印**指令
* 修正問題:**訓練模式**技能群組空白無法開啟瀏覽器視窗
* 修正問題:非子技能作者不應展開指令至使用者主技能
* 修正問題:**循環工作**內設定子技能為**條件執行**,條件一旦成立會持續成立
* Chromium 版本更新至 108.0.5359.215
### 2.1.20230130
* 新功能:新增 Cloud Processor [**Anti-Captcha**](./wap/anticaptcha.md) 模組
* 新功能:新增 Cloud Processor [**Google Drive**](./wap/googledrive.md) 模組
* 新功能:**工作資料夾執行腳本** api.zip 提供密碼加密
* 修正問題:登出帳號時應刪除使用者 session
* 修正問題:技能群組應保持原始大小寫
### 2.1.20230108
* 功能改進:Web Automation 支援 [CORS](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/CORS) 與 PKI 憑證讀卡
* 功能改進:版本更新支援手動下載
* 功能改進:主界面技能列表按照群組(瀏覽器資料庫名稱)分類管理
* 新功能:支援 antiCaptcha API
### 2.1.20221222
* 功能改進:Desktop Automation 增加 API 與 No-Code 功能選項
* 功能改進:Desktop Automation No-Code 與 Low-Code 切換時將 Editor 視窗提到最上層,避免被應用程式覆蓋
* 功能改進:增加 Sign Out 稽核紀錄
### 2.1.20221210
* 功能改進:Desktop Automation 增加 No-Code 功能選項與 API
* 功能改進:Desktop Automation Low-Code Editor 提供**執行選取部份程式碼**功能
* 功能改進:File Trigger 提供自訂**寫入延遲觸發**秒數
* Chromium 版本更新至 106.0.5249.199
### 2.1.20221129
* 修正問題:**PDF表單分析**WAP修正新版本解析器載入錯誤
* 功能改進:Web Automation **執行腳本**新增 Debugger 按鈕
* 功能改進:循環工作於**調整參數**提供**當循環中有錯誤**的選項:**繼續**以及**離開**
* 功能改進:**插入子技能**與**選擇子技能**提供**使用新瀏覽器執行子技能**選項
* 新功能:新增**DOCX轉HTML**與**資料夾管理**兩個WAP模組
* 功能改進:**EXCEL輸出** WAP 模組 api.setCell() 提供 style 物件參數以控制儲存格樣式
* Chromium 版本更新至 106.0.5249.181
### 2.1.20221114
* 新功能:支援 Abbyy OCR
* 功能改進:error.log 指令編號從 #1 開始
* 修正問題:抓取節點路徑例外處理
* 修正問題:上傳指令例外處理
### 2.1.20221028
* Chromium 版本更新至 106.0.5249.119
* 新功能:**SFTP** 模組支援 SFTP, FTP/TLS 與 FTP 協定
* 新功能:**工作資料夾執行腳本**模組新增 api.readCSV()
* 測試功能:**帳號設定**提供**防止使用者閒置自動登出**
### 2.0.20221009
* Chromium 版本更新至 104.0.5112.124
* 新功能:技能**調整**模式下插入新指令支援循環工作(與**訓練**模式相同,不支援巢狀循環)
* 新功能:技能**調整**模式下支援**多選刪除指令**功能
* 新功能:開放 WAP 新模組 SFTP
* 新功能:技能作者上傳技能時可開放其他使用者修改技能並上傳
### 1.8.20220920
* 新功能:**工作資料夾執行腳本**模組提供 zip 相關 API
* 新功能:**工作資料夾執行腳本**模組提供 stat API
* 新功能:新模組 **SFTP** 支援對指定 SFTP 伺服器上傳/下載檔案
* 新功能:技能**調整**模式下,支援**插入新指令**
### 1.8.20220917
* 新功能:技能調整模式下,新增**插入新指令**功能
* 新功能:**桌面自動化** Trainer UI 的 Crop List 提供 CLICK CROP AT X,Y 指令
* 新功能:**桌面自動化** Trainer UI 的 No-Code Editor 提供擷取選擇區域的 COPY X,Y,W,H 指令
### 1.8.20220807
* 新功能:**瀏覽器自動化**中**保存內容**指令提供將 HTML Table 存成 CSV 檔案
* 新功能:某些網站會改寫原生物件,例如 Promise,瀏覽器自動化中提供 JavaScript 原生物件的備份
* 修正問題:刪除**排程觸發**中的技能,在觸發後會堵住全自動處罰的序列
* 修正問題:**條件執行**套用在子技能指令時,會讓子技能中條件失效
* 修正問題:**桌面自動化**在 Trainer UI 中未解除 Low-Code Editor 選單就切換至 Live 模式會覆蓋介面
### 1.8.20220722
* 新功能:全自動觸發新增**檔案觸發**
* 新功能:**桌面自動化** No-Code 編輯區新增 OPEN FILE 指令
* 介面改善:**桌面自動化**減低訓練介面的覆蓋面積,讓 No-Code 編輯區可以涵蓋更多最大化的應用程式區域
### 1.8.20220708
* 新功能:**循環工作**新增**循環條件工作**選項,訓練時選取TXT文檔,設定文檔內容條件,符合條件時才執行循環內步驟
* 介面改善:**排程觸發**介面在排程項目超過7項時,底部功能會擋住第7個項目
### 1.8.20220625
* 新功能:技能動作選單提供**繼續訓練**功能(只提供給使用者自己訓練的技能)
* 新功能:技能設定提供**執行逾時(秒)**參數,預設0代表不設定逾時;正整數代表超過指定秒數強制結束技能執行
* 新功能:**API 觸發**提供詢問執行狀態 API
* 問題修正:api.run() 失敗時特定情況不會向外傳遞例外
### 1.8.20220617
* 新功能:**SQL執行分析** WAP 模組新增 MS-SQL server 支援
* 新功能:**桌面自動化** WAP 模組提供全螢幕 Native Trainer UI 與 auto code-gen
* 修正問題:**桌面自動化** WAP 模組 api.shell.trashItem() 在 Windows 系統機率性失敗
### 1.6.20220520
* 新功能:新增 **PowerShell** WAP 模組
* 新功能:Low-Code WAP api.write(filename, data, \{ mode: 0o744 \}) 提供寫入檔案的選項參數,與檔案系統的權限格式相同
* 功能改進:DA WAP 於同一次技能執行中,即便被子技能呼叫多次仍然只下載 crop 一次,省略多餘的下載時間
* Chromium 更新版本至 100.0.4896.160
### 1.6.20220512
* 新功能:執行結果頁新增**管理執行結果**功能,提供設定**通知頻率**與**結果保存期限**
* 功能改進:調整 Web **執行腳本**時會自動帶出 Debug Browser,作為修改腳本的測試執行環境
* 新功能:新增**圖表建立**模組
* 新功能:落地版伺服器管理後台新增使用者功能管理,包括**執行**、**訓練**、**排程觸發**、**郵件觸發**與**API觸發**
### 1.6.20220429
* 功能改進:**郵件觸發**的設定提供遮罩密碼選項,與郵件伺服器連線斷線時每隔10秒嘗試重連
* 新功能:新增**建立圖表**模組
* 新功能:**文件樣版套用**模組支援圖片樣版(只提供正式授權使用者)
### 1.6.20220423
* 新功能:訓練模式的任一 WAP模組中,快捷鍵 Cmd/Ctrl+D 代表啟動 Debugger,Cmd/Ctrl+R 代表 TEST,Cmd/Ctrl+E 代表打開工作資料夾
* 功能改進:訓練模式的 WAP 點擊 TEST 鍵後,當有輸出檔產生才會自動打開工作資料夾
### 1.6.20220416
* 功能改進:Low-Code 程式碼編輯器提供變換字型大小快捷鍵 Cmd/Ctrl +/-
* 新功能:工作資料夾執行腳本與 DA WAP api.writeCSV(filename, rows, header) 支援 header 參數
* 修正問題:Audi 汽車網站在訓練模式下異常
### 1.6.20220408
* Low-Code 程式碼編輯器更新
* 功能改進:DA WAP 會在每次 COMMIT 保存 Low-Code 程式碼與工作資料夾
* 功能改進:DA WAP Trainer UI 滑鼠游標停在 CROP 檔名上會提供預覽
* 功能改進:DA WAP Trainer UI 提供 ABORT,可用來停止執行中 Low-Code
* 功能改進:發送電子郵件 / 讀取電子郵件 WAP 密碼欄提供顯示切換
### 1.6.20220320
* 功能變更:取消 IE11 WAP,相關應用由 Desktop Automation WAP 提供
* 功能變更:**工作資料夾執行腳本** api.run() 產生的技能執行不再寄送執行完成郵件
* Chromium 版本更新至 98.0.4758.109
### 1.6.20220310
* 新功能:新增 EXCEL Writer WAP
* 新功能:新增 Google Sheet WAP
* 新功能:Google API Key 新增「複製憑證電子郵件」功能
* 新功能:訓練模式下,使用者可關閉瀏覽器視窗的載入彈窗
### 1.6.20220302
* 新功能:Desktop Automation WAP API screen.find, screen.waitFor, moveToCrop, clickCropt 支援 options 參數物件,使用者可以指定圖形辨識區域
* 新功能:Web Automation 網頁開啟新視窗可以支援三層以上
### 1.6.20220225
* 新功能:DOCX 樣版套用 WAP 支援 pptx 樣版
* 修正問題:多層瀏覽器視窗並執行下載會造成無回應
### 1.6.20220218
* 新功能:Web Automation **執行腳本**的腳本編輯視窗可以調整大小
* 新功能:Web Automation **執行腳本**支援跨站 iframe 的腳本執行
* 新功能:Web Automation **執行腳本**提供 querySelector, querySelectorAll API,可以不受阻斷DOM存取的網站影響,例如:salesforce
* 修正問題:瀏覽器視窗關閉後,session cookie 仍然存活至 EMILY App 關閉
* 修正問題:使用者取消登入彈窗時,不應該紀錄步驟
### 1.6.20220206
* 新功能:Web Automation 支援 DA mouse API
* 新功能:Desktop Automation WAP 支援 screen.capture 與 ocr API
* 新功能:提供 IE11 WAP,支援舊版 IE-only 網頁自動化
### 1.6.20220128
* 新功能:Web Automation 支援 NTLM 身分認證
* 新功能:**帳號設定**工具列提供使**用者論壇**入口
* 新功能:**工作資料夾執行腳本**與**桌面自動化** WAP 新增 ocr API
* 修正問題:瀏覽器核心停止回應時自動終止技能執行
### 1.6.20220121
* 新功能:Web Automation **執行腳本**支援更多滑鼠操作 API mouseDown, mouseUp, mouseClick, mouseDblClick, mouseContextmenu
* 新功能:Web Automation **執行腳本**支援清除 session 資料 API clearSessionData()
* 修正問題:**循環表格工作**在**條件執行**下會出現錯誤
### 1.6.20220112
* 新功能:Mac 版支援 Apple Silicon 的 CPU,例如 M1
* 新功能:Web Automation 自動關閉下載用子視窗
### 1.6.20220110
* 新功能:新增**保護資料**,利用作業系統金鑰加密文字資料
* 新功能:**API Trigger** 可設定 Port
* 新功能:**Schedule / Mail / API Trigger** 會統一排序
* 新功能:版本提示更新,使用者可選擇是否**下載更新**
* 新功能:語言選擇自動與作業系統同步
* 新功能:**Desktop Automation** WAP 整合 OpenCV
* Chromium 版本更新至 96.0.4664.110
### 1.5.20211224
* 新功能:**Web Automation** **插入腳本**與**工作資料夾執行腳本** WAP read(filename, encoding='utf8') API 支援編碼參數
* 新功能:**Desktop Automation** WAP 執行時會自動將主視窗與瀏覽器視窗縮小
* 修正問題:Windows 中文使用者名稱會造成技能訓練與執行失敗
### 1.5.20211126
* 新功能:支援從 **EMILY 安裝程式** 升級為 **EMILY APP**
* 新功能:**工作資料夾執行腳本** WAP 支援 googlesheet API
* 修正問題:訓練模式在 Windows 上選擇資料夾的技能於其他平台安裝時不會出現重新指定資料夾路徑
### 1.5.20211112
* 新功能:SKILL HUB 支援**複製**技能
* 新功能:Mail Trigger 如果被郵件伺服器斷線會自動嘗試重新連線
* 穩定性與安全性更新
### 1.5.20211016
* 新功能:Web Automation **身分認證**指令 username / password 支援 **%FILENAME%** 文檔變數
* 新功能:主視窗選單增加**線上文件**入口
* 新功能:**使用者填入資訊** WAP 新增 Password 資料類別
* 新功能:**PDF表單分析** WAP 新增 detectLine() / detectGroup() API
* 新功能:訓練模式下,WAP 存檔後支援倒退修改
### 1.5.20210924
* 新功能:Web Automation 中**循環表格工作**與**上傳檔案**支援 **%FILENAME%** 文檔變數
* Chromium 版本更新至 91.0.4472.164
### 1.5.20210918
* 新功能:**技能詳情**中可以更改 PARTITION
* 新功能:自動觸發的技能如果因使用者正在訓練或調整某技能將會放棄執行,並以郵件通知使用者。
* 修正問題:指定 **%FILENAME%** 變數於**匯出工作資料夾**或**建立檔案列表** WAP 中,安裝技能時不應該要求使用者選擇目標資料夾。
* 修正問題:execute.log 在網頁快速跳轉的情境下無法完整紀錄。
### 1.5.20210904
* 新功能 API Trigger:允許其他在同個網段的裝置以 HTTP API 觸發指定技能執行
* 新功能:提供**以技能名稱**或**以技能更新時間**排序技能
* HTTP Analyzer 新功能:增加請求內容格式 FORM
### 1.5.20210826
* 新 WAP:桌面自動化腳本
* 新功能:排程增加**每時**選項
* 新功能:訓練模式於**保存內容**、**執行腳本**、**等待節點**時選擇 sub-frame 節點會於 debugger console 列印 sub-frame url
### 1.5.20210820
* 新功能 Mail Trigger:設定郵件規則來觸發全自動技能執行
* 修正問題:直接關閉執行腳本的腳本編輯視窗會造成錯誤
* 修正問題:Web Automation 中 cross-site subframe 的執行腳本無法正常執行
### 1.2.20210722
* 需要指定輸入檔案的 WAP 支援 **%FILENAME%** 變數
* 新 WAP [**User Fill**](./wap/userfill.md) 用來讓使用者提供技能執行需要的文字資訊與檔案/資料夾路徑
* 教練模式技能管理新增 #hashtag 功能
### 1.2.20210715
* 新增非同步執行函式 api.writeCSV() 至**工作資料夾執行腳本**
* 修正問題:多個桌面啟動 EMILY 會產生多份程序造成相互影響
* 修正問題:api.splitCSV() 有機率無法執行完畢
### 1.2.20210708
* 新增同步執行函式 api.files() 至**工作資料夾執行腳本**
* 新增同步執行函式 api.rename() 至**工作資料夾執行腳本**
* 新增同步執行函式 api.remove() 至**工作資料夾執行腳本**
* 新增非同步執行函式 api.run() 至**工作資料夾執行腳本**
* 新增非同步執行函式 api.splitCSV() 至**工作資料夾執行腳本**
### 1.2.20210705
* 超過30天工作資料夾會自動刪除
* 工作資料夾產出 execute.log 輔助技能除錯
* Chromium 版本更新至 91.0.4472.124
* 修正問題:自動化某些嚴格 Same-Origin-Policy 的網站例如 Facebook 子技能會失敗
* 修正問題:過期帳號的測試執行邏輯錯誤
### 1.2.20210625
* **技能詳情**頁面提供技能**識別碼**欄位
* Web Automation **執行腳本**支援 run(uuid) 非同步執行其他技能於目前工作資料夾
* Web Automation **執行腳本**支援 download(url, filename) 下載指定連結至工作資料夾
### 1.2.20210618
* 訓練模式設定中,輸入完瀏覽器資料庫名稱可以直接按 ENTER 鍵取代點擊**開始**按鈕
* 訓練模式的**前往網址**支援 **%FILENAME%** 變數
* Web Automation 的**執行腳本**支援非同步執行,可回傳 Promise 物件
### 1.2.20210612
* 主視窗與訓練模式瀏覽器視窗加入編輯選單:copy/paste/cut
* 瀏覽器支援連結直接下載檔案
* 提供新腳本編輯器與腳本說明欄位
### 1.2.20210604
* 使用者手冊遷移至 https://docs.emily.tips
* SQL Executor WAP 支援 PostgreSQL
* mouse down, mouse up, click, input, select 步驟用戶可以調整目標節點路徑
### 1.2.20210531
* 支援多國語言機制,目前支援 ENU(英語美), CHT(中文繁)
* 可設定關閉自動更新檢查
* SQL Executor WAP 支援 Oracle DB
* Web Automation 腳本支援 mouseEnter, mouseMove, mouseEnd 用來模擬滑鼠移動
---
# 如何讓電腦全自動?
Source: https://docs.emily.tips/trigger/intro
> EMILY.RPA 全自動觸發總覽:排程、郵件、API、檔案與網頁觸發的選擇方式,以及在全自動觸發頁啟動的操作說明。
有了技能後,接下來是如何讓 EMILY.RPA 自動按照設定好的條件執行指定的技能。為達成這個目標,EMILY.RPA 提供排程觸發、郵件觸發、API觸發、檔案觸發、以及網頁觸發等功能,使用者可以選擇適合的觸發方式、觸發條件、指定的技能加入全自動觸發,然後點擊「**啟動**」就可以進入全自動模式。從版本 3.8.20251109 開始 EMILY.RPA 的各類觸發必須在全自動觸發頁啟動才會運作,這是為了提高全自動模式的穩定性與更好的執行狀態監控。

使用者在頁面右上角點擊「**啟動**」後,EMILY.RPA 就會進入全自動模式,此時設定的各類觸發才會開始運作,「**觸發工作佇列**」會顯示正在佇列中排隊的觸發技能,第一個項目為正在執行的觸發技能,按照佇列逐一執行,點擊佇列下方「**已完成工作**」列表項目可以開啟執行工作資料夾。

如果點擊「**離開**」按鈕時有正在執行的觸發技能,使用者可以點選「**立即停止全自動化模式**」彈窗的「**確認**」按鈕立即退出全自動模式,否則 EMILY.RPA 會等待正在執行的技能結束才退出,佇列中尚未執行的技能會被保留到下次進入全自動模式繼續執行。

如果希望 EMILY.RPA 一啟動就進入全自動模式,可以在「**帳號設定**」功能頁中打開「**啟動時進入全自動模式**」。其他各種觸發的設定可以參考個別觸發頁面的介紹。

---
# 排程觸發
Source: https://docs.emily.tips/trigger/schedule-trigger
> EMILY.RPA 排程觸發:依設定的時間條件自動執行指定技能,並說明系統時鐘準確度與 CPU 負載對觸發的影響。
排程觸發是讓 EMILY.RPA 按照設定的時間條件執行指定技能,也是最常見的觸發方式。由於觸發時間的參考來自本機系統時鐘,務必確認時鐘是準確的,另外由於 CPU 如果在觸發的時間繁忙,也可能造成延遲通知 EMILY.PRA 而導致判定觸發過期,因此需注意 CPU 負載,特別是安裝在虛擬機器(VM)容易因為實體 CPU 共用而引發這個問題。
### 建立排程
在「**我的技能**」功能頁點擊想要觸發的技能帶出選單,選擇「**排程**」選項。

### 設定時間條件
設定排程週期,共有「**每時**」、「**每日**」、「**每週**」、「**每月**」、「**每年**」五種,欄位可以填多個值以逗號分隔,例如以下例子是:每年3月與9月的1日與15日,時間 8:00, 8:30, 20:00, 20:30 都要執行。

### 管理排程
點擊「**全自動觸發**」功能頁的「**排程觸發**」,可以看到已建立的排程列表,也可以刪除不需要的排程。


---
# 郵件觸發
Source: https://docs.emily.tips/trigger/mail-trigger
> EMILY.RPA 郵件觸發:以 IMAP 檢查每一封新進郵件,符合規則時自動執行指定技能,並支援 Exchange Online 的 OAuth 2.0 授權登入。
郵件觸發是讓 EMILY.RPA 依照設定的規則檢查每一封新進的郵件,符合規則就觸發指定的技能。EMILY.RPA 與郵件伺服器溝通是透過 IMAP 協議,需與相關管理員確認本機可以成功連到郵件伺服器並綁定郵箱,如果郵件伺服器是 Exchange Online 則需要透過 OAuth 2.0 登入 Microsoft 帳號授權才能成功連線。
### 綁定郵箱
在「**全自動觸發**」功能頁點擊「**郵件觸發**」:

點擊界面下方的「**綁定郵箱**」圖示。

若不是使用 Exchange Online 郵件服務,`TYPE` 選 `IMAP` 並填寫其它欄位:

`HOST` 與 `PORT` 是 IMAP 郵件伺服器主機名稱與連線埠號,例如 imap.zoho.com / 993,可與郵件伺服器管理員確認。`USERNAME` 與 `PASSWORD` 是使用者在郵件伺服器設定的帳號名稱與帳號密碼,帳號通常與電子郵件地址相同。至於 `TLS/SSL` 選項代表與郵件伺服器的連線是否需要加密。
若是 Exchange Online 郵件服務,`TYPE` 選 `Exchange Online` 填寫其它欄位並點擊「**SIGN IN**」以信箱使用者的 Microsoft 帳號登入並授權,成功授權後 SIGN IN 按鈕文字會改成帳號。填寫的資訊可以參考 [Exchange Online 存取設定](/faq/config-exchange-online)。

最後點擊「**綁定郵箱**」頁面下方的「**確定**」後,如果成功會回到「**郵件觸發**」頁,上方會顯示成功綁定的郵箱名稱:

### 新增郵件觸發規則
點擊「**郵件觸發**」頁下方的「**新增郵件觸發規則**」圖示以建立新的郵件觸發規則:

郵件觸發規則頁需要輸入的欄位包括 `FROM` 是寄件者觸發關鍵字,可為完整電子郵件地址或部份字串,例如 `@company.com`。`SUBJECT` 是郵件主旨觸發關鍵字,可為主旨欄中的部份字串。例如完整的主旨為 `請貴司提供產品報價`,則觸發關鍵字可設定為 `報價`。`選擇技能` 則是從已安裝的自動化技能中,選擇當規則被觸發時要執行的技能。

郵件觸發規則由 `FROM` 與 `SUBJECT` 兩個欄位條件組成,必須同時滿足才會觸發技能執行。如果希望忽略某一欄位條件的檢查,則只需要將該欄位清空。例如:只要是 info@emily.tips 寄來的郵件都觸發技能執行,那麼只需要在 `FROM` 欄位填入`info@emily.tips`,`SUBJECT` 欄位留空就可以了。
### 觸發技能的輸入資料
每當郵件規則被觸發時,EMILY.RPA 會將來信郵件的寄件者、收件者、主旨、內文等四個欄位內容寫入工作資料夾,檔案名稱分別為:`mail-from.txt`、`mail-to.txt`、`mail-subject.txt`、`mail-text.txt`,並且會將來信的附件按原始檔案名稱存放在工作資料夾,作為觸發技能的輸入資料。
---
# API 觸發
Source: https://docs.emily.tips/trigger/api-trigger
> EMILY.RPA API 觸發:讓機器人成為伺服器,提供 HTTP API 端點網址讓其他系統呼叫並執行指定技能。
API 觸發是讓 EMILY.RPA 成為一台伺服器,提供端點網址讓其它系統以 HTTP API 觸發指定的技能,因此需要不會變動的 IP 地址或主機名稱,並確認發起請求的設備可以通過防火牆連到本機。
### 設定 API 伺服器
在「**全自動觸發**」功能頁點擊「**API 觸發**」。

點擊界面下方的「**調整參數**」圖示帶出「**API Port**」對話框,API 伺服器預設 3000 阜號,如果跟其他伺服器衝突可以調整,例如 3002,然後按「**確定**」。

### 將技能加入 API
在「**我的技能**」功能頁點擊想要觸發的技能帶出選單,選擇「**加入 API**」選項就可以將這個技能加入 API 服務的行列。

### 測試 API
設定完成後,需啟動全自動模式,這時 API 伺服器才會開始運作。剛才設定的阜號結合 EMILY.RPA 所在電腦的 IP 地址可以形成端點網址,我們可以使用 [Postman](https://www.postman.com/) 這類型發送 API 的工具軟體來測試 API 觸發。首先我們可以按照剛才設定的阜號發送一個 `GET http://localhost:3002/api` 請求來驗證 API 伺服器有正常運行,成功的話應該會看到類似下圖的回傳結果,包含使用者帳號 `userId`,是否正在執行觸發工作 `executing`,等待的工作有幾個 `waiting`,以及完成的工作有幾個 `finished`。

### 觸發技能
要觸發某個已加入 API 的技能需要技能識別碼 `uuid`,可以在進入全自動模式前的「**API 觸發**」頁找到。

端點網址的 uuid 參數即為欲執行的自動化技能識別碼,例如:`GET http://ip-address:port/api?uuid=1a2b` 表示為請求 EMILY.RPA 執行識別碼為 1a2b 的自動化技能;若希望上傳自動化技能需要的檔案作為輸入,可以採用 `POST http://ip-address:port/api?uuid=1a2b` 並將輸入檔案以 multipart/form-data 上傳,下圖以 HTTP 工具 Postman 為例,發送請求執行技能「**查詢維基百科並匯出檔案**」,同時傳送 `keyword.txt` 與 `invoice.png` 兩個檔案到這個技能的工作資料夾,伺服器會回傳工作佇列序號 `msUnixTime` 作為後續查詢狀態的參數。

### 詢問工作狀態
除了使用 `GET http://ip-address:port/api` 詢問工作佇列整體狀態外,也可以使用伺服器回傳的工作佇列序號 `msUnixTime` 查詢這個觸發技能的狀態。發送請求 `GET http://ip-address:port/api/job?uuid=1a2b&msUnixTime=1234` 來得到這個工作的目前狀態,狀態包括 inqueue / executing / finished:


---
# 檔案觸發
Source: https://docs.emily.tips/trigger/file-trigger
> EMILY.RPA 檔案觸發:監看指定的檔案或資料夾,當名稱或內容變動(含刪除)時自動執行指定技能。
檔案觸發是讓 EMILY.RPA 監看指定的檔案或資料夾,當監看的檔案或資料夾變動時執行指定的技能,變動包含名稱的改變與內容的改變,被刪除也算。
### 管理檔案觸發
在「**全自動觸發**」功能頁點擊「**檔案觸發**」進入觸發管理頁。

「**檔案觸發**」頁可以瀏覽或刪除已加入的觸發規則,下方提供「**新增檔案觸發規則**」或「**新增資料夾觸發規則**」按鈕,用來新增觸發規則。

### 新增觸發規則
點擊「**新增檔案觸發規則**」後進入「**設定監看檔案與觸發技能**」頁,然後點擊迴紋針圖示選取監看的檔案,並在下方「**選擇技能**」選單中選取檔案被改變時欲執行的技能後按「**確定**」。監看檔案被寫入新資料、刪除、改變檔案名稱都會造成觸發,其中寫入資料時會預設延遲 6 秒後啟動觸發,目的是讓短資料可以在大多數的情況下被完整寫入,以提供執行技能有完整的檔案資料,延遲秒數可以調整。如果寫入資料是無法預期結束時間,則建議技能內必須自行設計檢查機制。


---
# 網頁觸發
Source: https://docs.emily.tips/trigger/web-trigger
> EMILY.RPA 網頁觸發:讓機器人成為網頁伺服器,使用者從其他設備以瀏覽器載入網頁即可觸發指定技能。
網頁觸發是讓 EMILY.RPA 成為一個網頁伺服器,讓使用者可以從其他設備以瀏覽器載入這個網頁來觸發指定技能,因此需要不會變動的 IP 地址或主機名稱,並確認發起請求的設備可以通過防火牆連到本機。
### 設定網頁伺服器
在「**全自動觸發**」功能頁點擊「**網頁觸發**」。

點擊界面下方的「**調整參數**」圖示帶出「**Web Port**」對話框,網頁伺服器預設 3100 阜號,如果跟其他伺服器衝突可以調整,例如 3102,然後按「**確定**」。

### 將技能加入網頁觸發
在「**我的技能**」功能頁點擊想要觸發的技能帶出選單,選擇「**加入網頁觸發**」選項就可以將這個技能加入網頁服務的行列。

### 測試網頁
設定完成並進入全自動模式後,使用者可以在網路上可以拜訪到這個網址的電腦上,以標準瀏覽器如 Chrome / Firefox / Safari 連到網頁選擇技能來觸發.

---
# 遠端觸發
Source: https://docs.emily.tips/trigger/remote-trigger
> EMILY.RPA 遠端觸發:讓機器人成為流程代執行伺服器,可併聯多台提供負載平衡與高可用性,僅企業管理群組提供。
遠端觸發是讓 EMILY.RPA 成為一個流程代執行伺服器,讓使用者可以從其他設備以 EMILY.RPA 呼叫並執行指定技能,並將結果回傳,因此需要確認發起請求的設備可以本機。遠端觸發可以併聯多台 EMILY.RPA 提供負載平衡與高可用性的流程代執行服務,並注意只有企業管理群組才提供。
### 設定遠端伺服器
在「**全自動觸發**」功能頁點擊「**遠端觸發**」。

點擊界面下方的「**調整參數**」圖示帶出「**Remote Port**」對話框,伺服器預設 3200 阜號,如果跟其他伺服器衝突可以調整,例如 3202,然後按「**確定**」。

### 將技能加入遠端觸發
在「**我的技能**」功能頁點擊想要觸發的技能帶出選單,選擇「**加入遠端觸發**」選項就可以將這個技能加入網頁服務的行列。

### 測試遠端觸發
設定完成並進入全自動模式後,使用者可以在網路上可以拜訪到這個網址的電腦上,進入 Agentic Workflow 的「**SKILL**」頁面。

點擊「**REMOTE**」並點選需要的遠端技能加入技能列表。



最後測試看看是否能成功呼叫:

---
# 如何使用自動化模組?
Source: https://docs.emily.tips/wap/intro
> EMILY.RPA 自動化模組總覽:在訓練模式中選用自動化模組並加入技能流程的操作方式。
EMILY.RPA 提供多種自動化模組讓使用者在設計技能時可以按需求選用並加入流程。在訓練模式下點擊主界面的「**回到設計首頁**」按鈕。

## 設計首頁
設計首頁可以上下捲動,瀏覽所有的自動化模組。在網址列填入搜尋關鍵字時會即時過濾出名稱與說明包含關鍵字的所有模組,例如輸入 `郵件` 會過濾出跟郵件有關的模組。

也可以點擊設計首頁左上方的「**ASK EMILY**」,以自然語言詢問 AI 哪些模組可能可以滿足你的需求,甚至嘗試描述流程的大致過程,讓 AI 來建議應該考慮使用哪些模組。

## No-Code 編輯器
絕大多數的模組都提供 No-Code 無程式碼編輯器,可以編輯模組參數或指令。以「**發送電子郵件**」模組為例,如果規則標準沒有太多變化,使用者可以在 No-Code 編輯器直接設定電子郵件信箱的參數。如果欄位提示出現 **%VAR%** 或 **%FILENAME%** 表示這個欄位接受變數,其中變數名稱對應到工作資料夾中的文檔的主檔名。例如:`%name%` 的內容會被工作資料夾中 `name.txt` 的檔案內容取代。

## Low-Code 編輯器
需要高度彈性或複雜規則的模組通常會另外提供 Low-Code 低程式碼編輯器,例如**發送電子郵件**」郵件主旨與附件檔案想以當天日期做命名,這時就可以採用 Low-Code 以 JavaScript 編寫彈性的規則。[moment.js](https://momentjs.com/docs/) 與 [lodash](https://lodash.com/docs/4.17.15) 都是內建函式庫,可以直接使用。模組執行時會先將無程式碼指令依序執行完畢再執行低程式碼中的腳本。
Low-Code 建議使用「**ASK EMILY**」讓 AI 根據需求生成程式碼。

生成後可以直接在對話中提交與測試,如果程式碼有錯 AI 也會重寫,這樣可以提高效率。

### Low-Code 共用 API
提供 Low-Code 編輯器的自動化模組都提供存取工作資料夾檔案的同步函式如下:
* api.files() - 列出工作資料夾中所有的檔案
* api.read(filename, encoding='utf8') - 讀取工作資料夾中的指定檔案
* api.write(filename, data) - 寫入工作資料夾中的指定檔案
* api.rename(oldname, newname) - 修改工作資料夾中指定檔案的名稱
* api.remove(filename) - 移除工作資料夾中的指定檔案
```javascript
// 一筆筆列出所有工作資料夾中的檔案
api.files().forEach((file) => console.log(file))
// 用 lodash.js _.filter() 函式過濾出檔名為 'jpg' 結尾的檔案,
const files = api.files()
console.log(_.filter(files, (file) => file.endsWith('jpg')))
// 讀取工作資料夾中的文字檔 price.txt
console.log(api.read('price.txt'))
// 使用 moment.js 產生自訂格式的日期字串,並寫出文字檔到工作資料夾中
api.write('time.txt', moment().format('HH:mm:ss'))
// 修改工作資料夾中的檔案名稱
api.rename('time.txt', 'currentTime.txt')
// 刪除工作資料夾中的檔案
api.remove('price.txt')
```
---
# 使用者填入資訊
Source: https://docs.emily.tips/wap/userfill
> EMILY.RPA 使用者填入資訊模組:技能執行時彈出自訂表單讓使用者填入資訊,並寫入工作資料夾供後續模組與指令讀取。
這個模組提供表單讓使用者提供資訊作為流程後續指令的輸入。在訓練模式下設計一個表單讓使用者提供資訊,執行模式下當技能執行到這個模組時,會彈出設計的表單給使用者填入資訊並寫入工作資料夾,讓流程中後續的模組或指令可以讀取參考。

## No-Code 編輯器
### Overall Description
技能執行時提供這個表單的背景說明讓使用者了解表單收集資訊的目的。
### ADD
加入一個表單填寫項目,分為 「**Text**」、「**Password**」、「**File**」、「**Folder**」 四種選項,其中 File 與 Folder 是讓使用者提供檔案或資料夾的路徑。項目說明要讓使用者了解這個欄位的用途。在執行模式下,當使用者填寫完點擊「**DONE**」,模組會在工作資料夾依項目順序產生填寫內容的文字檔,檔案命名方式為 `userfill(n).txt` 其中 **n** 代表項目序號 **#n**,從零開始。
### RESET
清除所有表單上的項目。
### TEST
將目前表單填寫的項目內容輸出到工作資料夾。
---
# 工作資料夾執行腳本
Source: https://docs.emily.tips/wap/txt2txt
> EMILY.RPA 工作資料夾執行腳本模組:以 Low-Code 腳本對工作資料夾內的檔案做管理或讀寫。
對工作資料夾內的檔案做管理或讀寫。

## No-Code 編輯器
提供:「**重新命名檔案**」、「**刪除檔案**」、「**壓縮指定檔案**」、「**解壓縮指定檔案**」、「**解壓縮全部檔案**」等無程式碼指令。
例如想壓縮工作資料夾中的檔案存成 ZIP 檔,可以選擇「**壓縮指定檔案**」。然後將要壓縮的檔名排成 JSON 陣列格式填入 `FILES` 欄位,點擊「**OK**」後就會將這個無程式碼指令記錄在模組的指令列表。

## Low-Code 編輯器

### input 輸入物件
在腳本中可以直接存取 input 內建物件。input 物件中的每個 key 為工作資料夾中的一個 TXT 檔案名稱(不包含副檔名),每個 value 為該檔案的文字內容,在腳本被執行時就會自動載入所有文檔,免去於腳本中自行讀取的麻煩:
```javascript
// 讀取工作資料夾中 price.txt 的值
let price = input['price']
console.log('price:', price)
```
### output 輸出物件
當腳本需要輸出文檔時,可以直接修改 output 內建物件。加入 output 物件中的每個 key 將被輸出成工作資料夾中的一個 TXT 檔案,檔案名稱即為 key,文字內容為該 key 相對應的 value。
```javascript
// 寫入值到工作資料夾中 new_price.txt
let new_price = 100
output['new_price'] = new_price
```
### api 物件
提供同步函式:api.files(), api.stat(filename), api.read(filename, encoding='utf8'), api.write(filename, text), api.rename(oldname, newname), api.remove(filename), api.createHash(algorithm)。另外 [moment.js ](https://momentjs.com/docs/)與 [lodash](https://lodash.com/docs/4.17.15) 都是內建函式庫,可以直接使用:
```javascript
// 一筆筆列出所有工作資料夾中的檔案
api.files().forEach((file) => console.log(file))
// 讀取檔案的各類時戳資訊,例如檔案建立時間、修改時間、最近存取時間
console.log(api.stat('price.txt'))
// 讀取工作資料夾中的文字檔 price.txt
console.log(api.read('price.txt'))
// 寫出文字檔到工作資料夾中
api.write('time.txt', moment().format('HH:mm:ss'))
// 修改工作資料夾中的檔案名稱
api.rename('time.txt', 'currentTime.txt')
// 刪除工作資料夾中的檔案
api.remove('price.txt')
// 建立 MD5, SHA1, SHA256, SHA512 等演算法 hash 物件
let md5 = api.createHash('MD5')
// 輸出 MD5 hash 值
md5.hex('hello')
// 輸出 salt 為 'key' 的 hmac 值
md5.hex_hmac('key', 'hello')
```
以及非同步函式,回傳 [Promise](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Guide/Using_promises) 物件:api.run(uuid), api.readCSV(filename, separator, skiplines), api.splitCSV(filename, separator, skiplines, newname, maxRows), api.writeCSV(filename, rows, header) 與 api.writeXML(filename, obj, options)
```javascript
// 呼叫執行某個自動化技能,其識別碼為 ef4e12a6-636f-4e58-8e14-212089e6fd23
await api.run('ef4e12a6-636f-4e58-8e14-212089e6fd23')
// 將工作資料夾中的CSV格式大檔案分割成多個CSV格式小檔案,每個檔案不超過5000筆資料
let files = await api.splitCSV('large.csv', ',', 0, 'small.csv', 5000)
// 寫出的檔案:['small(0).csv', 'small(1).csv', ... ] 存成一個檔案列表
await api.writeCSV('list.csv', files.map((file, index) => {return {file, index}}), ['index','file'])
// 讀取工作資料夾中的CSV檔案並且印出資料
let list = await api.readCSV('list.csv')
console.log(list)
// 將 JSON 物件轉換成XML格式並寫出檔案,其中加上屬性,輸出header並縮排
let obj = {
root: [
{ date: '2023/03/12' },
{ item: 'coffee' },
{ item: 'tea' },
{
_name: 'addr',
_content: '101F, #1, Taiwan Road',
_attrs: {
country: 'TWN',
city: 'TPE'
}
}
]
}
await api.writeXML('result.xml', obj, { header: true, indent: '\t' })
```
另外也提供 zip 讀寫 API 以針對工作資料夾內的檔案做壓縮或解壓縮,此類 API 皆為非同步函式:
```javascript
// 讀取 input.zip 內檔案
let inputZip = api.zip()
await inputZip.load('input.zip')
let filesInZip = await inputZip.files()
filesInZip.forEach((file) => console.log(file))
// 解壓縮 input.zip 內的檔案 a.txt
await inputZip.extract('a.txt')
// 壓縮工作資料夾中 b.jpg 與 c.pdf 成 output.zip
let outputZip = api.zip()
await outputZip.add('b.jpg')
await outputZip.add('c.pdf')
await outputZip.save('output.zip')
```
如果在 Windows 上想解壓縮的 zip 檔內有中文檔名的檔案需要解壓卻發現出現亂碼錯誤,這是由於 Windows 的中文編碼不是 UTF-8,可以在 load(filename, encoding = 'utf8') API 中指定編碼模式。
```javascript
// assign encoding type in load()
await inputZip.load('input.zip', 'Big5')
```
需要對 PDF 檔案做刪除或合併頁面時,可以使用 pdf API:
```javascript
// 讀取 a.pdf 刪除第一頁後存成 b.pdf
let inputPdf = api.pdf()
await inputPdf.load('a.pdf')
let count = inputPdf.pageCount()
console.log(`a.pdf has ${count} pages`)
await inputPdf.removePage(0)
await inputPdf.save('b.pdf')
// 將 c.pdf 的第1,3,5頁,與 d.pdf 的第2頁合併成 e.pdf
let outputPdf = api.pdf()
await outputPdf.create()
await outputPdf.addPagesFrom('c.pdf',[0,2,4])
await outputPdf.addPagesFrom('d.pdf',[1])
await outputPdf.save('e.pdf')
```
---
# 匯出工作資料夾
Source: https://docs.emily.tips/wap/repo2dir
> EMILY.RPA 匯出工作資料夾模組:將工作資料夾中的檔案匯出到指定的目標資料夾,支援 %FILENAME% 變數。
匯出工作資料夾中的檔案。其中 `FOLDER` 爲匯出的目標資料夾,點擊「**PICK**」按鈕指定檔案路徑或使用 **%FILENAME%** 變數。

## No-Code 編輯器
提供:「**篩選檔案後匯出**」等無程式碼指令。例如,將工作資料夾中檔名包含 `report.pdf` 的檔案匯出到桌面。

## Low-Code 編輯器

### input 輸入陣列
在 input 陣列中每個元素代表一個工作資料夾的檔案,src 為原始檔名,dst 為目標檔名。
```javascript
// 印出工作資料夾中每個檔案的名稱
input.forEach((file) => console.log(file.src))
```
### output 輸出陣列
在 output 陣列中每個元素物件代表工作資料夾欲匯出的檔案,src 為原始檔名,dst 為目標檔名。
```javascript
// 將工作資料夾中所有檔案匯出,並在每個檔名前端加上一個固定字串 'auto'
input.forEach((file) => {
output.push({src: file.src, dst: 'auto-'+file.src})
})
```
---
# 建立檔案列表
Source: https://docs.emily.tips/wap/dir2csv
> EMILY.RPA 建立檔案列表模組:列舉指定資料夾中的檔案並寫入 output.csv 檔案。
列舉指定資料夾中的檔案並寫入 output.csv 檔案。其中 `FOLDER` 爲指定資料夾,點擊「**PICK**」按鈕指定檔案路徑或使用 **%FILENAME%** 變數。

## No-Code 編輯器
提供:「**重設 output.csv**」、「**過濾檔案至列表**」等無程式碼指令。例如,將桌面檔名有包含 `invoice` 的檔案加入 output.csv。

## Low-Code 編輯器

### input 輸入陣列
在 input 陣列中的每個元素代表一個指定資料夾內檔案的路徑。
```javascript
// 印出指定資料夾中每個檔案的路徑
input.forEach((filepath) => console.log(filepath))
```
### output 輸出陣列
在 output 陣列中的每個檔案路徑將被用來產生CSV格式檔案。
```javascript
// 將指定資料夾內的所有TXT檔建立一個CSV表
input.forEach((filepath) => {
if (filepath.endsWith('txt')) output.push(filepath)
})
```
---
# EXCEL表格處理
Source: https://docs.emily.tips/wap/excel2csv
> EMILY.RPA EXCEL 表格處理模組:以表格名、資料起始儲存格與表頭欄位將 EXCEL 資料正規化,處理後輸出 CSV 或 EXCEL 檔案。
EXCEL表格輸入處理後輸出成 CSV 或 EXCEL 格式檔案。利用指定表格名、資料起始儲存格、表頭欄位將載入資料正規化,呈現一致的資料結構(input輸入陣列)提供 Low-Code 應用處理。

## 參數
**`EXCEL`** - EXCEL 輸入檔,點擊「**PICK**」選取檔案、鍵盤輸入工作資料夾中的EXCEL檔名,或使用 **%FILENAME%** 變數。
**`SHEET`** - EXCEL 輸入表格名稱,留空代表為檔案中的第一個 sheet。
**`DATA CELL`** - 表格資料的起點(左上)儲存格A1表示法,不包含表頭。
**`HEADER`** - 輸入表格的表頭欄位命名陣列,有兩種 JSON 陣列表示法,第一種是簡單的一對一字串陣列,陣列中的第一個字串對應到表格的第一個表頭欄位,第二個字串則對應到第二個表頭欄位,中間不能跳過,以此類推:
```json
["A欄表頭名稱", "B欄表頭名稱", ...]
```
第二種是較為彈性的物件陣列,利用物件中的[正規表達式](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Guide/Regular_Expressions) regexp、偏移值 offset、A1 表示法等屬性作為定位表頭欄位的依據,再以物件中的 name 屬性值作為定位到的表頭欄位名稱:
```json
[
{
"regexp": "品名$", // 找到表格資料起點上方值符合”品名“結尾的儲存格
"name": "product" // 將找到的儲存格做為表頭欄位,並命名為”product"
},
{
"regexp": "品名$", // 找到表格資料起點上方值符合”品名“結尾的儲存格
"offset": 1, // 往右偏移一格
"name": "price" // 將找到的儲存格做為表頭欄位,並命名為"price"
},
{
"A1": "C", // 找到欄位C(以A1表示法來看)
"name": "stock" // 將找到的儲存格做為表頭欄位,並命名為"stock"
}
]
```
**`OUTPUT`** - 爲輸出檔案格式,有 CSV 與 XLSX 兩種。
## No-Code 編輯器
提供:「**重設 output.csv**」、「**排序**」、「**過濾**」等無程式碼指令。例如,將指定表格檔案以 `觸及率` 欄位 `DESCENDING` 遞減排序。

## Low-Code 編輯器

### input 輸入陣列
在 input 陣列中的每個物件元素代表輸入表格的一列資料,物件中的 key 為表頭欄位,value 為該欄位在這一列資料的值。
```javascript
// 印出輸入表格每筆資料的指定欄位
input.forEach((row, index) => {
console.log(index + '. 品名:' + row.product + ', 價格:' + row.price)
})
```
### output 輸出陣列
加入 output 陣列中的每個物件元素代表輸出表格的一列資料,物件中的 key 為表頭欄位,value 為該欄位在這一列資料的值。也可以利用 output.header 陣列指定輸出表格的標頭欄位:
```javascript
// 輸出價格高於 100 的表格,並加上 5% 的税
input.forEach((row) => {
if (row.price > 100) {
output.push({
name: row.product,
price: row.price,
tax: row.price * 0.05
})
}
})
// 指定表頭欄位
output.header.push('name','price','tax')
```
---
# EXCEL表格分析
Source: https://docs.emily.tips/wap/excel2txt
> EMILY.RPA EXCEL 表格分析模組:將 EXCEL 資料正規化為 input 陣列作為 Low-Code 分析來源,並將結果寫入工作資料夾文檔。
EXCEL表格分析。利用指定表格名、資料起始儲存格、表頭欄位將載入資料正規化,呈現一致的資料結構(input輸入陣列)作為 Low-Code 資料分析來源,結果寫入工作資料夾文檔

## 參數
**`EXCEL`** - EXCEL輸入檔,點擊「**PICK**」選取檔案、鍵盤輸入工作資料夾中的EXCEL檔名,或使用 **%FILENAME%** 變數。
**`SHEET`** - EXCEL輸入表格名稱,留空代表為檔案中的第一個 sheet。
**`DATA CELL`** - 表格資料的起點(左上)儲存格A1表示法,不包含表頭。
**`HEADER`** - 輸入表格的表頭欄位命名陣列,有兩種 JSON 陣列表示法,第一種是簡單的一對一字串陣列,陣列中的第一個字串對應到表格的第一個表頭欄位,第二個字串則對應到第二個表頭欄位,中間不能跳過,以此類推:
```json
["A欄表頭名稱", "B欄表頭名稱", ...]
```
第二種是較為彈性的物件陣列,利用物件中的[正規表達式](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Guide/Regular_Expressions) regexp、偏移值 offset、A1 表示法等屬性作為定位表頭欄位的依據,再以物件中的 name 屬性值作為定位到的表頭欄位名稱:
```json
[
{
"regexp": "品名$", // 找到表格資料起點上方值符合”品名“結尾的儲存格
"name": "product" // 將找到的儲存格做為表頭欄位,並命名為”product"
},
{
"regexp": "品名$", // 找到表格資料起點上方值符合”品名“結尾的儲存格
"offset": 1, // 往右偏移一格
"name": "price" // 將找到的儲存格做為表頭欄位,並命名為"price"
},
{
"A1": "C", // 找到欄位C(以A1表示法來看)
"name": "stock" // 將找到的儲存格做為表頭欄位,並命名為"stock"
}
]
```
## No-Code 編輯器
提供:「**Find By**」、「**Max By**」、「**Min By**」等無程式碼指令。例如,從指定表格中找到欄位 `來源` 包含 `google` 的資料列,將該筆資料的各欄位寫入工作資料夾文檔。

## Low-Code 編輯器

### input 輸入陣列
在 input 陣列中的每個物件元素代表輸入表格的一列資料,物件中的 key 為表頭欄位,value 為該欄位在這一列資料的值。
```javascript
// 印出輸入表格每筆資料的指定欄位
input.forEach((row, index) => {
console.log(index + '. 品名:' + row.name + ', 價格:' + row.price)
})
```
### output 輸出物件
加入 output 物件中的每個 key 將被輸出成工作資料夾中的一個 TXT 檔案,檔案名稱即為 key,文字內容為該 key 相對應的 value。
```javascript
// 寫入分析結果到工作資料夾中 total.txt
let total = 0
input.forEach((row) => total = total + row.price)
output['total'] = total
// 也可以利用 lodash 函式庫計算平均值
output['average'] = _.meanBy(input, 'price')
```
---
# EXCEL輸出
Source: https://docs.emily.tips/wap/excel
> EMILY.RPA EXCEL 輸出模組:複製指定 EXCEL 檔案的資料內容,以 Low-Code API 增修資料或樣式,產生新的 output.xlsx。
建立 XLSX 格式檔案。複製指定 EXCEL 檔案的資料內容,以 Low-Code 提供的 api 增修資料或樣式,產生新的 output.xlsx 檔案。

## 參數
**`EXCEL`** - EXCEL 輸入檔,點擊「**PICK**」選取檔案、鍵盤輸入工作資料夾中的EXCEL檔名,或使用 **%FILENAME%** 變數。這個檔案的內容會被加入輸出檔案 output.xlsx 讓 Low-Code 加工處理,如果毋需參考任何 EXCEL 的內容可以留空。
## Low-Code 編輯器
### api 物件
除了共通的檔案處理同步函式之外,另外還提供 api.addSheet(header, rows, name), api.delSheet(name), api.sheetNames(), api.mergeCells(name, startRow, startCol, endRow, endCol), api.getCell(name, row, col), api.setCell(name, row, col, value, style), api.setColWidth(name, col, width), api.setRowHeight(name, row, height) 等同步函式,使用方法可以參考以下範例:
```javascript
// 列出EXCEL檔的所有sheet
console.log(api.sheetNames())
// 加入新一頁 sheet
let rows = [{col1: 1, col2: '2'},{col1: 3, col2: '4'}]
api.addSheet(['col2','col1'], rows, 'new sheet')
// 合併儲存格:B2:C3
api.mergeCells('new sheet', 1, 1, 1, 2)
// 取得A1儲存格的值
console.log(api.getCell('new sheet', 0, 0))
// 寫入B2儲存格的值
api.setCell('new sheet', 1, 1, 'hello')
// 設定第1列(row為0)高度50
api.setRowHeight('new sheet', 0, 50)
// 設定C欄寬度為0(隱藏)
api.setColWidth('new sheet', 2, 0)
// 刪除 sheet
api.delSheet('new sheet')
```
也可以用**樣式物件**對指定儲存格設定樣式(只能支援 XLSX 格式),它的格式如下:
```javascript
// 樣式物件
const style = {
alignment: {
vertical: 'bottom', // 'top', 'center'
horizontal: 'left', // 'center', 'right'
wrapText: false, // true
},
font: {
name: 'Calibri', // font family name
sz: 12, // font size
color: { rgb: 'FF0000' },
bold: false, // true
italic: false, // true
underline: false, // true
strike: false, // true
},
fill: {
fgColor: { rgb: '00FF00' }
},
border: {
top: {
style: 'thin', // 'thick','dashed','dotted','hair','medium'
color: { rgb: '000000' }
},
bottom: {
style: 'thin',
color: { rgb: '000000' }
},
left: {
style: 'thin',
color: { rgb: '000000' }
},
right: {
style: 'thin',
color: { rgb: '000000' }
}
}
}
// 設定儲存格A1樣式
api.setCell('sheet name', 0, 0, 'style demo', style)
```
---
# EXCEL填值
Source: https://docs.emily.tips/wap/excelfiller
> EMILY.RPA EXCEL 填值模組:將值填入指定的 EXCEL 檔案,絕對路徑的檔案會先複製一份至工作資料夾再修改。
填入值至指定的 EXCEL 檔案,若指定檔案為絕對路徑,將複製一份至工作資料夾後再修改。

## 參數
**`XLSX FILE`** - EXCEL XLSX 格式輸入檔,點擊「**PICK**」選取檔案、鍵盤輸入工作資料夾中的 EXCEL 檔名,或使用 **%FILENAME%** 變數。
## No-Code 編輯器
提供:「**設定儲存格值**」、「**設定範圍值**」、「**設定表格到儲存格**」等無程式碼指令。例如,在 sheet2 表格的 A2 位置加入一個二維表格資料,A2 為 `2026-01-01`、B2 為 `1000`、A3 為 `2026-01-02`、B3 為 `450`。

## Low-Code 編輯器

### input 物件
input 物件就是 EXCEL 文件本身,提供同步函式 activeSheet(), sheet(sheetNameOrIndex), sheets()
```javascript
// 傳回正在使用中的sheet物件
let sheet0 = input.activeSheet()
// 傳回名稱為'商品'的sheet物件
let sheet1 = input.sheet('商品')
// 傳回第三個sheet物件(從零起算)
let sheet2 = input.sheet(2)
// 傳回所有sheet物件的陣列
let sheets = input.sheets()
```
### Sheet 物件
即表格物件,提供同步函式 cell(address), cell(rowNumber, columnNumber), range(address)
```javascript
// 傳回正在使用中sheet物件的'A1'儲存格
let cell0 = input.activeSheet().cell('A1')
// 傳回正在使用中sheet物件的第一列第一欄儲存格,跟'A1'一樣
let cell1 = input.activeSheet().cell(1,1)
// 傳回正在使用中sheet物件的指定範圍
let range = input.activeSheet().range('A1:C3')
// 將名為'商品'的sheet物件改名為'最新商品'
input.sheet('商品').name('最新商品')
```
### Cell 物件
即儲存格物件,提供同步函式 value(), value(value)
```javascript
// 傳回正在使用中sheet物件的'A1'儲存格的值
let value0 = input.activeSheet().cell('A1').value()
// 填入'hello'字串至正在使用中sheet物件的'A1'儲存格
input.activesheet().cell('A1').value('hello')
// 將3x3的二維陣列中的值填到'A1'為左上角起點的3x3個儲存格
let cellA1 = input.activeSheet().cell('A1')
cellA1.value([
[1,2,3],
[4,5,6],
[7,8,9]
])
// 將'B2'儲存格的公式印出
console.log(input.activeSheet().cell('B2').formula())
// 設定'C3'儲存格的公式
input.activeSheet().cell('C3').formula('A1+B2')
```
### Range 物件
即範圍物件,提供同步函式 value(), value(array2d)
```javascript
// 傳回正在使用中sheet物件的'A1:B2'範圍儲存格的值,以二維陣列表示
let values = input.activeSheet().range('A1:B2').value()
// 將2x2的二維陣列中的值填到'A1:B2'範圍的儲存格
input.activeSheet().range('A1:B2').value([
[1,2],
[3,4]
])
```
---
# CSV表格建立
Source: https://docs.emily.tips/wap/txt2csv
> EMILY.RPA CSV 表格建立模組:建立 CSV 格式檔案,常用於循環工作中收集網路資料後建置新的資料列。
建立 CSV 格式檔案,常被用來循環工作中收集網路資料後建置新資料列。

## 參數
**`OUTPUT FILENAME`** - 輸出於工作資料夾的 CSV 格式檔案名稱,如果檔案已存在工作資料夾內,內含的資料列將被預先載入 output 輸出陣列,讓腳本繼續新增資料列;腳本也可以主動刪除預載資料列讓輸出的表格重新開始。
## No-Code 編輯器
提供:「**新增一筆資料**」等無程式碼指令。例如,新增一筆資料,欄位 `product` 為 `A4 Paper`,欄位 `price` 為 `100`。

## Low-Code 編輯器

### input 輸入物件
在 input 物件中的每個 key 為工作資料夾中的一個 TXT 檔案名稱(不包含副檔名),每個 value 為該檔案的文字內容。
```javascript
// 讀取工作資料夾中 row-name.txt row-price.txt 的值
let name = input['row-name']
console.log('name:', name)
let price = input['row-price']
console.log('price:', price)
```
### output 輸出陣列
加入 output 陣列中的每個物件元素代表輸出表格的一列資料,物件中的 key 為表頭欄位,value 為該欄位在這一列資料的值。
```javascript
// 新增資料列,資料來自工作資料夾內的檔案,讀取部分參考上方範例
output.push({
name : name,
price : price,
tax: price * 0.05
})
// 指定表頭欄位,順序由左至右
output.header.push('name','price','tax')
```
---
# PowerShell
Source: https://docs.emily.tips/wap/powershell
> EMILY.RPA PowerShell 模組:執行 PowerShell 腳本,可用於控制本機已安裝的微軟 Office 等應用軟體。
執行 PowerShell 腳本。需注意若用來控制微軟 Office 應用軟體,應先確保該軟體在本機有被安裝並可使用。

## No-Code 編輯器
提供:「**從Outlook發送郵件**」、「**從Outlook讀取郵件**」、「**複製Excel工作表**」、「**將Excel匯出爲PDF**」等無程式碼指令。
例如,從本機的 Outlook 應用程式發送郵件到執行信箱 `jerry@emily.tips`,郵件主旨為 `Daily Report`,內文為 `請參考附件`,附件為工作資料夾中的 `report.pdf` 檔案。

## Low-Code 編輯器

在 Low-Code 編輯器中撰寫 PowerShell 腳本並執行,其執行產生的標準文字輸出會寫入工作資料夾 output.txt 檔案中。關於 PowerShell 腳本用法請參考[連結](https://learn.microsoft.com/zh-tw/powershell/)。
```powershell
# 範例:取得所有可用命令清單:
Get-Command
# 範例:取得所有作業系統上的程序列表
Get-Process
```
### ENABLE %VAR%
版本 2.2.20230225 以上,在 PowerShell 腳本中支援文檔變數 **%FILENAME%** 樣板。開啟後可在 PowerShell script 中以工作資料夾中 FILENAME.txt 的內容置換 script 中的 %FILENAME% 字串。
```powershell
# 將工作資料夾中 content.txt 的內容取代 %content% 後再交由 PowerShell 執行
Write-Output "%content%"
```
### 注意事項
在開啟 %VAR% 功能下,應避免在腳本註解(# 開頭)中出現百分比符號%。Low-Code 編輯器只支援命令(Cmdlet)序列執行,即從上至下按照順序逐行命令執行。如果需要進一步達成流程控制例如 for, foreach, if, switch, while, until 等指令,需要將腳本存成 ps1 檔案,再於 Low-Code 中呼叫:
```powershell
# myscript.ps1 印出 1~100
for ($i = 1; $i -le 100; $i++) {
Write-Output $i
}
```
```powershell
# PowerShell Low-Code, 呼叫上方的 ps1 腳本檔案
./myscript.ps1
```
Windows PowerShell 預設限制呼叫 ps1 檔案,此時可在 Windows 上利用管理員身分(Run as Administrator)啟動 Windows PowerShell 終端機模式,以 Set-ExecutionPolicy 命令更新設定為 RemoteSigned 即可:

PowerShell Low-Code 可以用來自動化 MS Office 的各種應用軟體,例如執行某個 Excel 檔案中的 VBA 巨集:
```powershell
# 定義 Excel 檔案的路徑
$filePath = "./excel.xlsm"
# 建立 Excel 物件
$excel = New-Object -ComObject Excel.Application
# 開啟 Excel 檔案
$workbook = $excel.Workbooks.Open($filePath)
# 呼叫 VBA Macro "VBA_Macro_Name"
$excel.Run("VBA_Macro_Name")
# 關閉 Excel 檔案並釋放記憶體
$workbook.Close()
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null
```
---
# PDF表單分析
Source: https://docs.emily.tips/wap/pdf2txt
> EMILY.RPA PDF 表單分析模組:分析 PDF 檔案並擷取文字資訊,建議使用符合 PDF/A 標準的檔案。
分析指定 PDF 格式檔案並擷取文字資訊。請注意指定的 PDF 檔案應符合 [PDF/A 標準](https://zh.wikipedia.org/zh-tw/PDF/A)。
模組上方可選擇「**VIEW**」「**TRAIN**」兩種模式。在「**TRAIN**」模式中可以進行程式碼編寫,在「**VIEW**」模式中則可對該文件進行預覽,文件換頁則可透過左邊下拉頁碼選單操作。


## 參數
**`PDF`** - PDF 格式輸入檔,支援ISO標準的PDF/A格式,點擊「**PICK**」選取檔案、鍵盤輸入工作資料夾中的 PDF 檔名,或使用 **%FILENAME%** 變數。
**`PASSWORD`** - PDF 格式輸入檔密碼,可使用 **%FILENAME%** 變數。
### 座標系統
模組中使用 Page Normalized Coordinate(PNC) 座標系統。原點位於文件第一頁的左上角 (0,0),每一頁的座標範圍正規化至相鄰的整數。座標以 (x,y) 表示,其中 x 或 y 都可以帶小數,第一頁的座標範圍是 (0,0) 至 (1,1),第二頁則是 (0,1) 至 (1,2) 依此類推,例如 (0.5,1.5) 代表座標在第二頁的正中間。
### 文字物件
模組解析指定檔案後會產出文件中所有的文字物件,物件中除了文字內容外,也會包含文字的座標。

## No-Code 輔助編輯器 (VIEW)
「**VIEW**」輔助編輯器可以在文件預覽畫面上以滑鼠鍵盤的組合操作來產生 Low-Code 需要的程式碼。在輔助編輯器中將滑鼠移到頁面文字上可以標示文字物件與座標,另外也可以透過滑鼠與鍵盤的組合操作來自動產生程式碼,使用者在完成操作後產生的程式碼會被存在剪貼簿中,可以切換到 Low-Code 編輯器中直接貼上,或進一步修改。
### 抓取文字物件

### 產生邊界

### 方向解析

### 範圍解析

### 相對區域解析

## Low-Code 編輯器 (TRAIN)
### input 輸入物件
輸入物件是將PDF檔案轉換後的資料物件,其中包含了統一坐標系後的所有文字物件,線條物件...,以及解析所需的函式。
```javascript
Doc{
totalPages, // 文件的總頁數
pageInfo[], // 頁面資訊,如頁面的畫素寬度/高度
textData[], //文字物件陣列
hLines[], // 橫線陣列
vLines[], // 縱線陣列
blocks[], // 方格(由縱橫線組成)陣列
tables[], // 表格陣列(由方格組成)陣列
}
```
文字物件是解析文件所使用的最小單位物件,每個文字物件都帶有以下的屬性:
```javascript
textObject{
text, // 文字物件的內文
LT{}, // 文字物件左上角座標
LB{}, // 文字物件左下角座標
RT{}, // 文字物件右上角座標
RB{}, // 文字物件右下角座標
C{}, // 文字物件中央點座標
w, // 文字物件寬度
h, // 文字物件高度
block{}, // 紀錄該文字物件與文件表格的關係
isDeleted(), // 檢測文字物件是否被橫線劃過
detectLine(dir), // 檢測並回傳最近的線條, dir可為"up","down","left","right"
detectGroup(), // 偵測並回傳鄰近線條相同的所有的文字物件,可用於偵測同一格內的所有文字物件。
}
```
### 解析函式

輸入物件提供了數個解析函式與工具函式能幫助使用者在空間中找出目標物件。整體的解析邏輯在於使用空間(spatial)或字詞(textual)上的條件縮小文字物件的集合,接著用相對關係找到目標物件。
```javascript
textObj = input.getKeyObj( keyName, keyBounds, options )
// keyName: 文字物件的內文字串
// keyBounds: 找尋範圍的物件,格式為 {"top":num,"bottom":num,"left":num,"right":num,“page”:num}
// options: 選項物件,可提供下列選項
// “regExp”: 使用正規表達式過濾搜尋範圍
// “ignoreHeader”: 忽略每一頁上方範圍的資料,範圍由小數定義(頁高百分比)
// “ignoreFooter”: 忽略每一頁下方範圍的資料,範圍由小數定義(頁高百分比)
// “all”: 布林值,若開啟則函式回傳所有找到的文字物件(陣列形式)
```
```javascript
textObj = input.resolve( target, options )
// target: 目標物件,包含鍵值物件(keyObj)或是(keyName/keyBounds)的組合,解析方向(valPos),解析範圍(valBounds)或是相對解析範圍(relValBounds)
// options: 選項物件,可提供下列選項
// “regExp”: 使用正規表達式過濾搜尋範圍
// “ignoreHeader”: 忽略每一頁上方範圍的資料,範圍由小數定義(頁高百分比)
// “ignoreFooter”: 忽略每一頁下方範圍的資料,範圍由小數定義(頁高百分比)
```
```javascript
textObjs[] = input.resolveRange( target, options )
// target: 目標物件,包含起始鍵值物件(startKeyObj)或是(startKeyName/startKeyBounds)的組合,結尾鍵值物件(endKeyObj)或是(endKeyName/endKeyBounds)的組合,解析方向(valPos),解析範圍(valBounds)或是相對解析範圍(relValBounds)\
// options: 選項物件,可提供下列選項
// “regExp”: 使用正規表達式過濾搜尋範圍
// “ignoreHeader”: 忽略每一頁上方範圍的資料,範圍由小數定義(頁高百分比)
// “ignoreFooter”: 忽略每一頁下方範圍的資料,範圍由小數定義(頁高百分比)
```
```javascript
[實驗性功能] textObjs[] = input.resolveTable( target, options )
// target: 目標物件,包含鍵值物件(keyObj)或是(keyName/keyBounds)的組合,解析方向(valPos),解析範圍(valBounds)或是相對解析範圍(relValBounds)
// valType: 解析模式,可以為 ROW,ROW(Num),COL,COL(Num),REPEAT。
// ROW/COL模式會解析整行/整列的資料
// ROW(Num)/COL(Num)模式會解析鍵值右方/下方的Num個值資料。
// REPEAT模式會解析所有相似表格中的位於鍵值位置資料。
// options: 選項物件,可提供下列選項
// “regExp”: 使用正規表達式過濾搜尋範圍
// “includeKey”: 布林值,如果為真,解行列解析的回傳值會包含target中的鍵值。
// “tableRefs”: 一個物件陣列,格式如下{“refText”:string, “R”:num, “C”:num}。此物件陣列用以定義"相似表格"需要具有那些相同內容。
```
### 工具函式
```javascript
strings[] = input.textGrouping( textObjs , option)
// textObjs: 需要被重整的文字物件陣列
// Option: 排列方式選項,可以是 LINES, TDLR, LRTD(default)
// Note: 排序邏輯會將行高低於1.5倍/間距小於2個字寬的文字物件群組。接著將每個群組使用TDLR,LRTD的順序排序。並依序輸出每個群組的字串
// Note2: LINES模式則會以高度位於同一行高的方式分群,並以逐行的方式回傳字串。
```
```javascript
textObjs[] = input.textSort( textObjs, mode = 0)
// textObjs: 需要被重整的文字物件陣列
// Mode: 排序模式,目前只有左至右,上至下的物件排序。
// Note:回傳新的排序後陣列。
```
```javascript
num = input.checkBounds( keyBounds, textObj )
// (0 為無重疊, 1 為部分重疊, 2 為物件包含於範圍內)
// keyBounds: 欲測試的範圍。格式如{top:num, bottom:num, left:num, right:num}
// textObj: 欲測試的文字物件
```
### output 輸出物件
加入 output 物件中的每個 key 將被輸出成工作資料夾中的一個 TXT 檔案,檔案名稱即為 key,文字內容為該 key 相對應的 value。
## 範例
```javascript
// 1.Resolve single value by Name:
let target = {keyName:"PRODUCTION ORDER", keyBounds = "page":1, valPos:"RIGHT" }
let productOrderNum = input.resolve( target );
// result: productOrderNum.text = “423022”
// 2.Resolve single value by object:
let orderObj = getKeyObj("PRODUCTION ORDER", {page:1})
let target = {keyObj: orderObj, valPos:"RIGHT"}
let productOrderNum = input.resolve( target );
// result: productOrderNum.text = “423022”
// 3.Resolve single value with regExp Filter:
let target = { keyName:"Coord #", keyBounds = {page:1, valPos:"RIGHT"}
let options = {“regExp”:/\d{2}\/\d{2}\/\d{2}/ }
let issueDate = input.resolve( target, options );
// result: issueDate .text = “06/24/20”
// 4.Resolve multiples values by start/endKeyObjects:
let startObj = input.getKeyObj( "Ship Type", {page:1} )
let endObj = input.getKeyObj( "Ship Terms", {page:1} )
let target = {startKeyObj:startObj, endKeyObj:endObj, valPos:"RIGHT"}
let interData = input.resolveRange(target)
//Result: interData[0].text = “AW”
//Result: interData[1].text = “Ship Via"
//Result: interData[2].text = “SEA”
// 5.Resolve multiples values by valBounds:
let sellerObj = getKeyObj("To (Seller):", {page:1})
let codeObj = getKeyObj({"Code:", {page:1})
let accObj = getKeyObj("Acc Sup:", {page:1})
let target = {valBounds:{top:sellerObj.LB.y, right:accObj.LB.x, bottom:codeObj.LT.y, page:1 } }
let address = input.resolveRange(target)
//Result: address[0].text = “TAIEASY INTERNATIONAL. CO., LTD”
//Result: address[1].text = “11F., NO. 1, JIHU RD., NEIHU DIST.,"
//Result: address[2].text = “TAIPEI CITY 114,”
//Result: address[3].text = “TAIWAN (R.O.C.)”
//Result: address[4].text = “TAIPEI CITY, TAIWAN”
// 6.Resolve multiples values by relValBounds
let facObj = getKeyObj("Mfrag Fac:", {page:1})
let target = {relValBounds:{top: -0.01, right:0.25, bottom:0.09, left:0.0} }
let location= input.resolveRange(target)
//Result: location[0].text = “FORMOSA VIET NAM TEXTILE INDUSTRY”
//Result: location[1].text = “CO.,LTD"
//Result: location[2].text = “MY XUAN A2 INDUSTRIAL ZONE, MY XUAN”
//Result: location[3].text = “WARD,”
//Result: location[4].text = “PHU MY TOWN, BA RIA - VUNG YAU”
// 7.Resolve value with ignore options
let buyerObj = input.getKeyObj("By Buyer",{page:1})
let target = {keyObj:buyerObj, valPos:"DOWN"}
let options = {ignoreHeader:0.22, ignoreFooter:0.85}
let downVal= input.resolveRange(target, options)
// downVal.text = ”To (Seller)”
// 8.Resolve block values in Table.
let target = {keyName:"DESC", keyBounds:{page:1}, valPos:"DOWN"}
let blockVal= input.resolve(target)
// blockVal.text = “TRAINER PANT”
let allBlockVal = input.resolveTable({keyObj:blockVal})
// allBlockVal.text = “TRAINER PANT
// YOUTH”
// 9.Resolve row blocks values in Table.
let target = {keyName:"Ship Via", keyBounds:{page:1}, valType:"ROW"}
let blockVals = input.resolveTable(target)
// blockVals[0].text = “Ship Type”
// blockVals[1].text = “AW”
// blockVals[2].text = “Ship Via”
// blockVals[3].text = “SEA”
// blockVals[4].text = “Ship Terms”
// blockVals[5].text = “FOB”
target.valType = "ROW"
blockVals = input.resolveTable(target);
// blockVals[0].text = “SEA”
// blockVals[1].text = “Ship Terms”
// blockVals[2].text = “FOB”
target.valType = "ROW2"
blockVals = input.resolveTable(target);
// blockVals[0].text = “SEA”
// blockVals[1].text = “Ship Terms”
// 10.Resolve Column/Row blocks values in Table.
let target = {keyName:"Coord #", keyBounds:{page:1}, valType:"COL5"}
let options = {includeKey:true}
// get 6 headers in first column
let colVals = input.resolveTable(target, options)
// get row values for each header
colVals.forEach( head => {
let rowVals = input.resolveTable({keyObj:head, valType:"ROW0"})
})
// for “Coord #” row
// rowVals[0].text = “TRAINING”
// rowVals[1].text = “PO Issue Date”
// rowVals[2].text = “06/24/20”
// for “Season” row
// rowVals[0].text = “204HO”
// rowVals[1].text = “Last Revised Date”
// rowVals[2].text = “06/24/20”
// for “Payment Terms” row
// rowVals[0].text = “75 DAY TERMS THROUGH GT NEXUS”
// for “Ship Type” row
// rowVals[0].text = “AW”
// rowVals[1].text = “Ship Via”
// rowVals[2].text = “SEA”
// rowVals[3].text = “Ship Terms”
// rowVals[4].text = “FOB”
// for “Ref#” row
// rowVals[0].text = “204HO NTM056 YRR PNP A”
// for “Bene” rows
// rowVals[0].text = “NTM064 TAIEASY INTERNATIONAL CO.,LTD”
// 11.Resolve repeat blocks values in Table.
// find first origin
let target = {keyName:"Country of Origin", keyBounds:{“page":1}, “valPos”:”RIGHT”}
let originVal = input.resolve(target)
// originVal.text = “Vietnam”
// Resolve origins in other tables
let options = { tableRefs: [
{refText:"Item:", R:0, C:0},
{refText:"Country of Origin", R:1, C:0}
]}
let blockVals = this.resolveTable({keyObj:originVal, valType:"RIGHT"})
// blockVals[0].text = “VietNam”
// blockVals[1].text = “Taiwan”
// blockVals[2].text = “China”
```
---
# 發送電子郵件
Source: https://docs.emily.tips/wap/smtp
> EMILY.RPA 發送電子郵件模組:以 SMTP 協議連接郵件伺服器發送電子郵件,並說明 HOST、PORT、TLS/SSL 等參數設定。
使用 SMTP 協議連接郵件伺服器發送電子郵件,信箱設定參數依使用的電子郵件服務或伺服器而定。

## 參數
**`HOST`** - SMTP 郵件伺服器主機名稱,例如 smtp.gmail.com。
**`PORT`** - SMTP 郵件伺服器連線埠號,預設為常用的 465。
**`TLS/SSL`** - SMTP 郵件伺服器是否需要 TLS/SSL 加密。
**`USERNAME`** - 使用者在郵件伺服器設定的帳號名稱,可以使用 **%FILENAME%** 變數。
**`PASSWORD`** - 使用者在郵件伺服器設定的帳號密碼,可以使用 **%FILENAME%** 變數。
**`RECIPIENT`** - 收件人地址。如果有多個收件人,以逗號分隔表示,支援 **%FILENAME%** 樣板,例如:
```
alice@mail.com,bob@mail.com,%contact%
```
**`CC`** - 副件抄送地址,多人寫法如上。
**`SUBJECT`** - 郵件標題,支援 **%FILENAME%** 樣板。
**`USE HTML`** - 爲郵件內文樣板是否採用 HTML 語法。
**`MAIL TEMPLATE`** - 郵件內文樣板,支援 **%FILENAME%** 樣板。
```
Dear %user%
Thanks for subscribing %serviceName% service.
```
**`ATTACHMENT`** - 加入指定附件,為正規表達式字串:`invoice-[0-9]{3}\.jpg`
### EMBED IMAGE
郵件內文要開啟 USE HTML,將圖檔加入附件,並且在郵件內文中用 \
標籤引用附件中的圖檔:

請注意在 \
標籤中來源屬性 src 需以 `cid:` 為前綴引用附件中的圖檔。
## Low-Code 編輯器

### input 輸入物件
input 物件為以上填寫的內容,可以在這裡做送出前的修改。
```javascript
// 先印出填好的郵件內容,再做送出前的修改
console.log(input)
// 內文加上日期
input.text += `\n\n Sent on ${moment().format('YYYY-MM-DD')}`
// 密件發給 archive@company.com
input.bcc = 'archive@company.com'
```
---
# 讀取電子郵件
Source: https://docs.emily.tips/wap/imap2csv
> EMILY.RPA 讀取電子郵件模組:以 IMAP 協議連接郵件伺服器讀取電子郵件,信箱參數依使用的郵件服務而定。
使用 IMAP 協議連接郵件伺服器讀取電子郵件,信箱設定參數依使用的電子郵件服務或伺服器而定。

## 參數
**`HOST`** - IMAP 郵件伺服器主機名稱,例如 imap.gmail.com。
**`PORT`** - IMAP 郵件伺服器連線埠號,預設為常用的 993。
**`TLS/SSL`** - IMAP 郵件伺服器是否需要TLS/SSL加密。
**`USERNAME`** - 使用者在郵件伺服器設定的帳號名稱,可以夾帶 **%FILENAME%** 變數插入工作資料夾內檔名為 FILENAME.txt 的TXT檔案內容,達到動態指定的效果。
**`PASSWORD`** - 使用者在郵件伺服器設定的帳號密碼,支援 **%FILENAME%** 變數。
**`MAILBOX`** - 郵件信箱名稱。
**`SINCE DAY(S) AGO`** - 讀取自幾天前的郵件。
**`UNREAD ONLY`** - 是否選擇只讀取未讀郵件。
## No-Code 編輯器
提供:「**重置 output.csv**」、「**過濾郵件**」等無程式碼指令。例如,過濾出來自 `@emily.tips` 網域,主旨包含 `採購單` 的郵件,寫入到工作資料夾的 output.csv。

## Low-Code 編輯器

### input 物件陣列
在 input 物件陣列中的每個元素代表讀取自指定郵件信箱的每封郵件:
```javascript
// 印出讀取到的每封郵件主旨與寄件者
input.forEach((mail) => {
console.log('from:' + mail.from + ', title:' + mail.subject)
})
```
### output 物件陣列
加入 output 陣列中的每個物件元素代表輸出表格的一列資料,物件中的 key 為表頭欄位,value 為該欄位在這一列資料的值,最後表格將被輸出成工作資料夾內的 output.csv 檔案。
```javascript
// 將讀取的每封郵件文字欄位輸出到CSV,並且將附件檔案存檔
input.forEach((mail) => {
output.push({
from: mail.from,
subject: mail.subject,
date: mail.date.toLocaleString(),
})
if (mail.attachments.length > 0) {
mail.attachments.forEach((att) => {
api.write(att.filename, att.content)
})
}
})
// 指定表頭欄位
output.header.push('from','subject','date')
```
### api 物件
除了提供同步函式:api.files(), api.read(filename, encoding='utf8'), api.write(filename, text), api.rename(oldname, newname), api.remove(filename) 存取工作資料夾內的檔案;另外提供 mail 物件與相關非同步函式 api.mail.moveto(uid, mailbox), api.mail.remove(uid)
```javascript
// 找到標題包含'促銷'的郵件
let mail = _.find(input, (m) => m.subject.includes('促銷'))
// 移到'Trash'郵件資料夾
await api.mail.moveto(mail.uid, 'Trash')
// 找到標題包含'中獎'的郵件
mail = _.find(input, (m) => m.subject.includes('中獎'))
// 移除郵件
await api.mail.remove(mail.uid)
```
---
# Exchange 發送電子郵件
Source: https://docs.emily.tips/wap/smtp-exchange
> EMILY.RPA Exchange 發送電子郵件模組:以 SMTP 發送 Exchange Online 電子郵件,需使用支援 Exchange Online 的帳號。
以 SMTP 發送 Exchange Online 電子郵件,必須使用支援 Exchange Online 的帳號,填寫的資訊可以參考 [Exchange Online 存取設定](/faq/config-exchange-online)。

## 參數
**`TENANT ID`** - 使用者郵件帳號在 Azure Portal 開的 Azure Active Directory 租用戶識別碼。
**`CLIENT ID`** - 上述的「**租用戶**」中新增註冊的「**企業應用程式**」用戶端識別碼。
**`CLIENT SECRET`** - 填入上述「**用戶端密碼**」的值。
**`ACCOUNT`** - 填完 `TENANT ID`、`CLIENT ID` 與 `CLIENT SECRET` 後,點擊「**SIGN IN**」會帶出瀏覽器讓使用者完成身分認證,並自動帶入 `ACCOUNT`。
**`RECIPIENT`** - 收件人地址。如果有多個收件人,以逗號分隔表示,支援 **%FILENAME%** 樣板,例如:
```
alice@mail.com,bob@mail.com,%contact%
```
**`CC`** - 副件抄送地址,多人寫法如上。
**`SUBJECT`** - 郵件標題,支援 **%FILENAME%** 樣板。
**`USE HTML`** - 爲郵件內文樣板是否採用 HTML 語法。
**`MAIL TEMPLATE`** - 郵件內文樣板,支援 **%FILENAME%** 樣板。
```
Dear %user%
Thanks for subscribing %serviceName% service.
```
**`ATTACHMENT`** - 加入指定附件,為正規表達式字串:`invoice-[0-9]{3}\.jpg`
### EMBED IMAGE
郵件內文要開啟 USE HTML,將圖檔加入附件,並且在郵件內文中用 \
標籤引用附件中的圖檔:

請注意在 \
標籤中來源屬性 src 需以 `cid:` 為前綴引用附件中的圖檔。
## LOW-CODE 編輯器

### input 輸入物件
input 物件為以上填寫的內容,可以在這裡做送出前的修改。
```javascript
// 先印出填好的郵件內容,再做送出前的修改
console.log(input)
// 內文加上日期
input.text += `\n\n Sent on ${moment().format('YYYY-MM-DD')}`
// 密件發給 archive@company.com
input.bcc = 'archive@company.com'
```
---
# Exchange 讀取電子郵件
Source: https://docs.emily.tips/wap/imap2csv-exchange
> EMILY.RPA Exchange 讀取電子郵件模組:以 IMAP 讀取 Exchange Online 電子郵件,需使用支援 Exchange Online 的帳號。
以 IMAP 讀取 Exchange Online 電子郵件,必須使用支援 Exchange Online 的帳號,填寫的資訊可以參考 [Exchange Online 存取設定](/faq/config-exchange-online)。

## 參數
**`TENANT ID`** - 使用者郵件帳號在 Azure Portal 開的 Azure Active Directory 租用戶識別碼。
**`CLIENT ID`** - 上述的「**租用戶**」中新增註冊的「**企業應用程式**」用戶端識別碼。
**`CLIENT SECRET`** - 填入上述「**用戶端密碼**」的值。
**`ACCOUNT`** - 填完 `TENANT ID`、`CLIENT ID` 與 `CLIENT SECRET` 後,點擊「**SIGN IN**」會帶出瀏覽器讓使用者完成身分認證,並自動帶入 `ACCOUNT`。
**`MAILBOX`** - 郵件信箱名稱。
**`SINCE DAY(S) AGO`** - 讀取自幾天前的郵件。
**`UNREAD ONLY`** - 是否選擇只讀取未讀郵件。
## No-Code 編輯器
提供:「**重置 output.csv**」、「**過濾郵件**」等無程式碼指令。例如,過濾出來自 `@emily.tips` 網域,主旨包含 `採購單` 的郵件,寫入到工作資料夾的 output.csv。

## LOW-CODE 編輯器

### input 物件陣列
在 input 物件陣列中的每個元素代表讀取自指定郵件信箱的每封郵件:
```javascript
// 印出讀取到的每封郵件主旨與寄件者
input.forEach((mail) => {
console.log('from:' + mail.from + ', title:' + mail.subject)
})
```
### output 物件陣列
加入 output 陣列中的每個物件元素代表輸出表格的一列資料,物件中的 key 為表頭欄位,value 為該欄位在這一列資料的值,最後表格將被輸出成工作資料夾內的 output.csv 檔案。
```javascript
// 將讀取的每封郵件文字欄位輸出到CSV,並且將附件檔案存檔
input.forEach((mail) => {
output.push({
from: mail.from,
subject: mail.subject,
date: mail.date.toLocaleString(),
})
if (mail.attachments.length > 0) {
mail.attachments.forEach((att) => {
api.write(att.filename, att.content)
})
}
})
// 指定表頭欄位
output.header.push('from','subject','date')
```
### api 物件
除了提供同步函式:api.files(), api.read(filename, encoding='utf8'), api.write(filename, text), api.rename(oldname, newname), api.remove(filename) 存取工作資料夾內的檔案;另外提供 mail 物件與相關非同步函式 api.mail.moveto(uid, mailbox), api.mail.remove(uid)
```javascript
// 找到標題包含'促銷'的郵件
let mail = _.find(input, (m) => m.subject.includes('促銷'))
// 移到'Trash'郵件資料夾
await api.mail.moveto(mail.uid, 'Trash')
// 找到標題包含'中獎'的郵件
mail = _.find(input, (m) => m.subject.includes('中獎'))
// 移除郵件
await api.mail.remove(mail.uid)
```
---
# 發送 HTTP 請求
Source: https://docs.emily.tips/wap/http2txt
> EMILY.RPA 發送 HTTP 請求模組:發送 HTTP 請求並以 Low-Code 分析回應內容。
發送 HTTP 請求並分析回應。

## 參數
**`METHOD`** - 選擇發送 HTTP 請求的方法:**GET, POST, PUT, DELETE, HEAD**
**`ENDPOINT`** - 接收 HTTP 請求的端點網站,例如:https://google.com
**`HEADERS`** - HTTP [請求標頭欄位](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)物件,例如:
```javascript
{
"Content-Type": "application/json"
}
```
**`TEXT`** - 如果請求內容為文字或 JSON 資料格式,請選擇 `TEXT`,並在 `TEXT AS BODY` 填寫內容。
**`FILE`** - 如果請求內容為上傳檔案,則選擇 `FILE`,並點擊 `FILE AS BODY` 中的 📎 圖示選取檔案。以上兩種請求內容格式最必須於 `HEADERS` 指定 Content-Type。
**`FORM`** - 如果選擇 `FORM` 內容格式,則需以 JSON 資料格式填寫 FormData,但不需要於 `HEADERS` 中指定 Content-Type,於 FormData 中夾帶檔案必須指名工作資料夾中的檔案名稱並且須具備副檔名,如下面例子,夾帶工作資料夾中的 avatar.jpg 檔案,其欄位名為 "avatar":
```javascript
{
"username": "emily",
"avatar": "avatar.jpg"
}
```
## No-Code 編輯器
提供:「**將回應內容存成檔案**」等無程式碼指令。例如,「**將回應內容存成檔案**」可將回應的 `url`、`status`、`headers`、`contentType`、`body` 寫入工作資料夾中的文檔。
## Low-Code 編輯器

### input 輸入物件
input 輸入物件為 HTTP 回應內容:
```javascript
// input 輸入物件
{
url, // 請求的完整網址
status, // 回應狀態碼
contentType, // 回應內容的 MIME type
headers, // 回應表頭
body, // String 或是 Uint8Array
}
```
### output 輸出物件
加入 output 物件中的每個 key 將被輸出成工作資料夾中的一個 TXT 檔案,檔案名稱即為 key,文字內容為該 key 相對應的 value。
```javascript
// 將回應中內容輸出到工作資料夾
if (input.contentType === 'application/json') {
let jsonBody = JSON.parse(input.body)
_.forEach(jsonBody, (value, key) => {
output[key] = value
})
}
if (input.contentType === 'image/png') {
api.write('result.png', input.body)
}
```
---
# 終端機命令列
Source: https://docs.emily.tips/wap/commandline
> EMILY.RPA 終端機命令列模組:執行本機終端機命令列,可用指令視本機作業系統而定。
執行本機終端機命令列,指令視本機作業系統而定。

與本機的終端機或命令列模式相同,執行結果輸出到工作資料夾內 output.txt 檔案,以 Mac 或 Linux 電腦為例:
```bash
ls -al
```
產生的 output.txt 內容如下:
```
total 56
drwxr-xr-x 7 jt.strad staff 224 Jun 6 10:56 .
drwx------ 328 jt.strad staff 10496 Jun 6 09:35 ..
-rw-r--r--@ 1 jt.strad staff 6148 Jun 6 09:36 .DS_Store
-rw-r--r-- 1 jt.strad staff 302 Jun 6 09:36 output.csv
-rw-r--r-- 1 jt.strad staff 531 Jun 6 10:56 output.txt
-rw-r--r-- 1 jt.strad staff 8090 Jun 6 10:49 result.png
-rw-r--r-- 1 jt.strad staff 15 Jun 6 10:48 slideshow.txt
```
**%FILENAME% 變數**也可以用在命令列中:
```shell
ls -al %dir%
```
---
# 文件樣板套用
Source: https://docs.emily.tips/wap/docxtemplate
> EMILY.RPA 文件樣板套用模組:將動態內容套用到指定的文件樣板,產生 DOCX 或 PPTX 文件。
將動態內容套用到指定的文件樣板檔案產生 DOCX/PPTX 文件。

## 參數
**`DOCX/PPTX TEAMPLTE`** - 用來產生動態內容的 DOCX/PPTX 樣板檔案,點擊「**PICK**」選取或使用 **%FILENAME%** 變數。


## No-Code 編輯器
提供:「**文字樣板**」、「**陣列樣板**」、「**圖片樣板**」等無程式碼指令。例如,加入一個陣列資料到 `陣列樣板`。

## Low-Code 編輯器

**`文字樣板`** - 以字串取代樣板變數,例如 `%title%` 以 `產品明細` 取代。
**`陣列樣板`** - 以 JSON 陣列內容取代樣板變數。如果在表格中塞入陣列樣板,表格會按照陣列資料長度自行往下新增表格列,如果希望在文本中自動換行可以在陣列結尾變數前加入換行。例如 `%#products%` `%name%` `%amount%` `%price%` `%/products%` 以下方陣列取代:
```
[
{
"name": "咖啡",
"amount": 10,
"price": 100
},
{
"name": "紅茶",
"amount": 5,
"price": 80
}
]
```
**`圖片樣板`** - 以 PNG 圖片取代樣板變數。例如 `%img.chart1%` 以 `chart1.png` 圖片取代。
### input 輸入物件
在 input 物件中的每個 key 為工作資料夾中的一個 TXT 檔案名稱(不包含副檔名),每個 value 為該檔案的文字內容。
```javascript
// 讀取工作資料夾中 title.txt products.txt 的值
let title = input['title']
console.log('title:', title)
let products = JSON.parse(input['products'])
console.log('products:', products)
```
### output 輸出物件
對應到 DOCX/PPTX 樣板檔案內容中的變數 %key%,output 物件必須指定 output\[‘key‘] 的 value;對應到 DOCX 樣板檔案內容中的陣列變數 %items%,output 物件必須指定資料陣列至 output\[‘items‘] 的 value:
```javascript
// DOCX 樣板檔案中定義了 %title% 與 %#products% %name% %amount% %price% %/products%
output['title'] = title
output['products'] = products
// 插入工作資料夾中的 PNG 檔
output['img.chart1'] = 'chart1.png'
```
---
# SQL 執行分析
Source: https://docs.emily.tips/wap/sqlexecutor
> EMILY.RPA SQL 執行分析模組:連線指定資料庫執行 SQL 指令,並以 Low-Code 分析處理執行結果。
連線指定資料庫執行 SQL 指令並分析處理執行結果。

## 參數
**`TYPE`** - 選擇資料庫種類。支援 `mysql`、`postgres`、`oracle`、`mssql` 等種類資料庫。
**`HOST`** - 資料庫主機,可以為 IP address 或主機網域名稱。
**`PORT`** - 資料庫主機埠號。
**`USER`** - 連線資料庫的使用者帳號名稱,支援 **%FILENAME%** 變數。
**`PASSWORD`** - 連線資料庫的使用者帳號密碼,支援 **%FILENAME%** 變數。
**`DATABASE`** - 資料庫名稱,支援 **%FILENAME%** 變數。
**`SQL STATEMENT`** - 對指定資料庫執行的 SQL 指令,**%FILENAME%** 樣板:
```
SELECT * from %price%;
```
## No-Code 編輯器

## Low-Code 編輯器

### input 輸入陣列
在 input 陣列中的每個元素代表 SQL 查詢到的每一筆資料,物件中的 key 為查詢表格的欄位,value 為該欄位在這一筆資料的值。
### output 輸出物件
加入 output 物件中的每個 key 將被輸出成工作資料夾中的一個 TXT 檔案,檔案名稱即為 key,文字內容為該 key 相對應的 value。
```javascript
// 寫入分析結果到工作資料夾中 total.txt
let total = 0
input.forEach((row) => total = total + row.price)
output['total'] = total
```
---
# SFTP
Source: https://docs.emily.tips/wap/sftp
> EMILY.RPA SFTP 模組:連線至指定的 FTP/SFTP 伺服器上傳或下載檔案。
連線至指定的 FTP/SFTP 伺服器上傳或下載檔案。

## 參數
**`TYPE`** - 傳輸協議,支援 `SFTP`、`FTP/TLS`、`FTP`。
**`HOST`** - FTP/SFTP 主機,可以為 IP address 或主機網域名稱。
**`PORT`** - SFTP 或 FTP 主機埠號。
**`USERNAME`** - 使用者帳號名稱。
**`PASSWORD`** - 使用者帳號密碼。
## No-Code 指令
提供:「**下載檔案**」、「**上傳檔案**」等無程式碼指令。例如,從參數指定的 SFTP 伺服器上下載一個檔案。

## Low-Code 腳本

### api 物件
除了提供同步函式:api.files(), api.read(filename, encoding='utf8'), api.write(filename, text), api.rename(oldname, newname), api.remove(filename) 存取工作資料夾內的檔案;另外提供 ftp 物件與相關非同步函式 api.ftp.list(path), api.ftp.get(path, filename), api.ftp.put(filename, path), api.ftp.mkdir(path), api.ftp.rename(path, newpath), api.ftp.remove(path) 如下:
```javascript
// 列出伺服器根目錄中的檔案或子資料夾
let entries = await api.ftp.list('/')
console.log(entries)
// 下載伺服器中路徑為 /download/test.png 的檔案到工作資料夾,並命名為 file1.png
await api.ftp.get('/download/test.png', 'file1.png')
// 更換在伺服器路徑為 /download/test.png 的檔名
await api.ftp.rename('/download/test.png', '/download/testnew.png')
// 上傳工作資料夾中 file2.pdf 檔案到伺服器的路徑 /upload/file2.pdf
await api.ftp.put('file2.pdf', '/upload/file2.pdf')
// 在伺服器路徑為 /upload/temp 建立子資料夾
await api.ftp.mkdir('/upload/temp')
// 刪除在伺服器路徑為 /upload/file2.pdf 的檔案
await api.ftp.remove('/upload/file2.pdf')
```
---
# 圖表建立
Source: https://docs.emily.tips/wap/csv2chart
> EMILY.RPA 圖表建立模組:從指定的 CSV 格式資料來源產生圖表影像檔 output.png。
從指定的 CSV 格式資料來源產生圖表影像檔 output.png。

## 參數
**`CSV`** - 符合 CSV 格式的資料來源,可點擊 PICK 選取檔案路徑,或輸入檔名以使用工作資料夾的檔案,也可以使用 **%FILENAME%** 變數。
## 輸入檔案
Chart 模組在解析 CSV 資料時,一般欄位表頭將用來繪製圖表的橫軸座標,每一資料列相對應欄位表頭的數值則用來繪製圖表的縱軸座標,請注意只有數值型別的資料才會被用來繪製圖表,其他型別例如文字將被忽略。而 `_chart` 為字首的特殊欄位表頭將被模組視為圖表設定參數,例如:
**`_chartLabel`** - 表示該資料列的標題。
**`_chartType`** - 表示該資料列的圖表型別,共有:`bar`、`line`、`area` 三種型別。
**`_chartColor`** - 表示該資料列的圖表顏色,為 CSS 顏色表示法,例如:`red`、`#00ff55`

## 輸出檔案
訓練模式中按下「**TEST**」將觸發模組繪製圖表,並輸出 output.png 至工作資料夾:

---
# DOCX 轉 HTML
Source: https://docs.emily.tips/wap/docx2html
> EMILY.RPA DOCX 轉 HTML 模組:將 DOCX 檔案轉換成 output.html,後續可用網頁自動化工具擷取內容。
將指定的 DOCX 檔案轉換成網頁寫入工作資料夾中的 output.html,後續可利用網頁自動化的工具擷取內容。

## 參數
**`DOCX`** - DOCX輸入檔,點擊「**PICK**」選取或使用 **%FILENAME%** 變數。
## 輸出檔案
輸出一個 output.html 檔案於工作資料夾中,供後續步驟或模組使用。
---
# 資料夾管理
Source: https://docs.emily.tips/wap/folder
> EMILY.RPA 資料夾管理模組:以 Low-Code 對指定資料夾中的檔案進行管理操作。
管理指定的資料夾。

## 參數
**`FOLDER`** - 指定的資料夾,點擊「**PICK**」按鈕指定或使用 **%FILENAME%** 變數。
## No-Code 編輯器
提供:「**重新命名檔案**」、「**刪除檔案**」、「**建立資料夾**」等無程式碼指令。例如,將指定的資料夾中檔案名稱為 `output.csv` 改名為 `order.csv`。

## Low-Code 編輯器

### input 輸入物件
在 input 物件中的每個 key 為工作資料夾中的一個 TXT 檔案名稱(不包含副檔名),每個 value 為該檔案的文字內容。
### output 輸出物件
加入 output 物件中的每個 key 將被輸出成工作資料夾中的一個 TXT 檔案,檔案名稱即為 key,文字內容為該 key 相對應的 value。
### api 物件
提供非同步函式:api.files(), api.folders(), api.stat(name), api.rename(oldname, newname), api.remove(name), api.mkdir(dirname)
```javascript
// 列出指定資料夾中的檔案
let files = await api.files()
console.log(files)
// 列出指定資料夾中的資料夾
let folders = await api.folders()
console.log(folders)
// 讀取指定資料夾中的檔案或子資料夾的各類時戳資訊,例如檔案建立時間、修改時間、最近存取時間
let info = await api.stat('subfolder')
console.log(info)
// 修改指定資料夾中的檔案
await api.rename('report1.pdf', 'report2.pdf')
// 刪除指定資料夾中的檔案
await api.remove('price.pdf')
// 在指定資料夾中建立子資料夾
await api.mkdir('newfolder')
```
---
# Google Drive
Source: https://docs.emily.tips/wap/googledrive
> EMILY.RPA Google Drive 模組:存取 Google Drive 中特定的資料夾或檔案,需要 2.1.20230130 以上版本。
存取 Google Drive 中特定資料夾或檔案,需要 2.1.20230130 以上版本

## 參數
**`File ID`** - 指定 Google Drive 資料夾或檔案的 ID,支援 **%FILENAME%** 變數,從瀏覽器網址列中可以取得,例如:
```
https://drive.google.com/drive/folders/[FileID] // 資料夾
https://docs.google.com/document/d/[FileID] // 文件
https://docs.google.com/spreadsheets/d/[FileID] // 試算表
https://drive.google.com/file/d/[FileId] // 檔案
```
## No-Code 編輯器
提供:「**上傳檔案到資料夾**」、「**從資料夾下載檔案**」等無程式碼指令。例如,將工作資料夾中的 `order.pdf` 檔案上傳到 Google Drive 指定資料夾。

## Low-Code 編輯器
### input 物件
為指定 File ID 的 Google Drive 物件。若為資料夾物件,支援 list(), upload(filename), createFolder(foldername), createSpreadsheet(filename) 等非同步函式;若為檔案物件,則支援 download(filename), moveto(folderID) 等非同步函式:
```javascript
// 指定的 File ID 為資料夾時,列出此資料夾中的所有物件,並下載所有檔案
let items = await input.list()
console.log(items)
// 當物件支援download(filename)函式時,將資料夾的檔案物件下載
for (const item of items) {
if (item.download) await item.download()
}
// 指定的 File ID 為資料夾時,上傳一個工作資料夾中的檔案
let file = await input.upload('image.jpg')
console.log(file)
// 指定的 File ID 為資料夾時,建立一個名為 'subfolder' 子資料夾
let folder = await input.createFolder('subfolder')
console.log(folder)
// 指定的 File ID 為資料夾時,建立一個 Google Spreadsheet 檔案
let file2 = await input.createSpreadsheet('mysheet')
console.log(file2)
// 指定的 File ID 為檔案時,下載此檔案到工作資料夾
await input.download()
// 將檔案移動到指定的資料夾
await input.moveto('fileIDxxx')
```
---
# Google Sheets
Source: https://docs.emily.tips/wap/googlesheet
> EMILY.RPA Google Sheets 模組:讀寫指定的 Google Spreadsheet 檔案。
讀寫指定的 Google Spreadsheet 檔案。

## 參數
**`Spreadsheet ID`** - 想要寫入資料的目標 Google Spreadsheet ID,支援 **%FILENAME%** 變數,從瀏覽器網址列中可以取得,例如:
```
https://docs.google.com/spreadsheets/d/[SpreadsheetID]/
```
## No-Code 編輯器
提供:「**下載 XLSX**」、「**下載 CSV**」等無程式碼指令。例如,從指定的 Google Spreadsheet 檔案,將 `sheet1` 表格下載到工作資料夾的 output.csv 檔。

## Low-Code 編輯器

### api 物件
除了常用的檔案處理同步函式 api.files(), api.read(filename, encoding='utf8'), api.write(filename, text), api.remove(filename) 之外,可以使用同步函式 api.sheetNames() 取得試算表的標題陣列:
```javascript
// 印出所有試算表的標題
console.log(api.sheetNames())
```
非同步函式包括 api.addSheet(header, rows, name), api.delSheet(name), api.getRows(name), api.addRows(name, rows), api.delRow(name, rowIndex), api.getCell(name, rowIndex, colIndex), api.setCell(name, rowIndex, colIndex, value), api.loadSheet(name, range):
```javascript
// 新增一個標題為 “new sheet” 的試算表
let header = ['姓名','電子郵件']
let rows = [
{'姓名':'Alice','電子郵件':'alice@mail.com'},
{'姓名':'Bob','電子郵件':'bob@mail.com'}
]
await api.addSheet(header, rows, 'new sheet')
// 刪除一個標題為 “old sheet” 的試算表
await api.delSheet('old sheet')
// 新增數筆資料到標題為 “new sheet“ 的試算表
let rows2 = [{'姓名':'Candy','電子郵件':'candy@mail.com'}]
await api.addRows('new sheet', rows2)
// 讀取標題為 “new sheet“ 的試算表資料
let rows3 = await api.getRows('new sheet')
console.log(rows3)
// 刪除第三列, 從零算起, 不包含標頭列
await api.delRow('new sheet', 2) // row of 'Candy' will be deleted
// 讀取儲存格, 從零算起, 有包含標頭咧
let cell = await api.getCell('new sheet', 2, 0)
console.log(cell) // 'Bob'
// 寫入儲存格, 從零算起, 有包含標頭列
await api.setCell('new sheet', 2, 0, 'Bob Wang')
// 讀取指定名稱的 sheet
let sheet = await api.loadSheet('sheet1')
// 或是以A1表示法指定範圍
sheet = await api.loadSheet('sheet1', 'A1:E5')
// 取得儲存格,(row,col)座標為(0,1),座標為 zero-based
let cell1 = await sheet.cell(0,1)
// 指定儲存格的值
cell1.value = 'Jerry'
// 取得座標為(1,1)的儲存格,row/col(zero-based)
let cell2 = await sheet.cell(1,1)
// 指定儲存格的值
cell2.value = 'New Taipei City'
// 儲存所有在 sheet 的編輯結果
await sheet.save()
```
---
# Google 文字辨識
Source: https://docs.emily.tips/wap/img2txt
> EMILY.RPA Google 文字辨識模組:使用 Google 雲端 OCR 服務,從影像類檔案中解析文字資訊。
使用 Google 雲端 OCR 服務,從影像類檔案中解析文字資訊,input 為 OCR 解析回傳的結果。

## 參數
**`IMAGE FILE`** - 影像輸入檔,可為 jpg 或 png 格式,點擊「**PICK**」選取檔案、鍵盤輸入工作資料夾中的檔名,或使用 **%FILENAME%** 變數。
## Low-Code 編輯器
### input 物件
```javascript
{
// Google OCR 返還物件
aiReponse: {
fullTextAnnotation, // 參考 TextAnnotation 定義
... // 其他可忽略
}
textData, // 擷取的文字塊陣列
}
```
input.aiResponse.fullTextAnnotation 保存從 Google OCR 返還的辨識結果,可以參考 [TextAnnotation](https://docs.cloud.google.com/vision/docs/reference/rest/v1/AnnotateImageResponse#textannotation),全文辨識的字串可以從 input.aiResponse.fullTextAnnotation.text 取得。
---
# Google 自然語言理解
Source: https://docs.emily.tips/wap/txt2sentiment
> EMILY.RPA Google 自然語言理解模組:使用 Google 雲端 NLU 服務,解析文字檔案中的正負面情緒與強度。
使用 Google 雲端 NLU 服務,解析文字檔案中的正負面情緒與強度,input 為 NLU 解析回傳的結果。

## 參數
**`TXT FILE`** - 文字輸入檔,點擊「**PICK**」選取檔案、鍵盤輸入工作資料夾中的檔名,或使用 **%FILENAME%** 變數。
## Low-Code 編輯器
### input 物件
```javascript
{
documentSentiment, // 整體文件的情緒與強度
language, // 指定文件的語言
sentences // 句子情緒強度陣列
}
```
input 物件保存 Google NLU 返還的完整結構,參考 [回傳資料結構](https://docs.cloud.google.com/natural-language/docs/reference/rest/v1/documents/analyzeSentiment#response-body)
---
# Azure 文字辨識
Source: https://docs.emily.tips/wap/azureformrecognizer
> EMILY.RPA Azure 文字辨識模組:使用 Azure 雲端服務從影像類檔案解析文字與表格資訊,需要 2.2.20230211 以上版本。
使用 Azure 雲端文字辨識服務,從影像類檔案中解析文字與表格資訊,input 為 Azure 解析回傳的結果,需要 2.2.20230211 以上版本。

## 參數
**`IMAGE FILE`** - 影像輸入檔,可為 pdf / jpg / png 格式,點「**PICK**」選取檔案、鍵盤輸入工作資料夾中的檔名,或使用 **%FILENAME%** 變數。
**`ENDPOINT`** - 在 Azure 中開出的表格辨識器服務端點。
**`API KEY`** - 在 Azure 中開出的表格辨識器金鑰。
**`MODEL ID`** - 填上 Azure 訓練好的 Model ID,現成的模型有:`prebuilt-layout`、`prebuilt-document`、`prebuilt-read`、`prebuilt-invoice`、`prebuilt-receipt`、`prebuilt-idDocument`、`prebuilt-businessCard` 等,一般用途可以嘗試使用 `prebuilt-layout`,也可以採用自行訓練的模型,詳情請參考[連結](https://learn.microsoft.com/en-us/azure/applied-ai-services/form-recognizer/concept-model-overview?view=form-recog-3.0.0)。
## 申請 Azure API Key
在開始使用這個模組之前,你需要到 Microsoft Azure 開一個帳號,並且建立一個訂閱單位 Subscription:

接著就可以建立表格辨識器,一般而言如果是這個帳號的第一個表格辨識器,可以選 F0 Free Tier,每個月可以免費辨識500頁:

最後將建立好的表格辨識器服務端點與金鑰儲存備用:

## Low-Code 編輯器
### input 物件
input 為 Azure OCR 返還的辨識結果,可以參考 Azure 線上官方文件 [AnalyzeResult](https://learn.microsoft.com/zh-tw/javascript/api/%40azure/ai-form-recognizer/analyzeresult?view=azure-node-latest)。
```javascript
{
content, // 全文辨識的字串
documents,
pages,
paragraphs,
style,
tables
}
```
---
# Anti-Captcha
Source: https://docs.emily.tips/wap/anticaptcha
> EMILY.RPA Anti-Captcha 模組:針對圖形驗證碼的影像文字辨識,需要 2.1.20230130 以上版本。
針對圖形驗證的影像文字辨識,需要 2.1.20230130 以上版本。

## 參數
**`IMAGE FILE`** - 圖形驗證的影像檔案,點擊「**PICK**」選取或使用 **%FILENAME%** 變數。
**`API KEY`** - 在 [anti-captcha.com](https://anti-captcha.com) 申請的金鑰。

---
# JSON API Server
Source: https://docs.emily.tips/wap/http2json
> EMILY.RPA JSON API Server 模組:建立可回覆 JSON 資料格式的 HTTP API 伺服器,會持續等待請求直到收到 DELETE 請求。
建立一個可回覆 JSON 物件資料格式的 HTTP API 伺服器。請注意,由於這個模組是伺服器,除非請求方發送 DELETE 的請求或設定錯誤時停止伺服器並遇到錯誤,否則模組會保持等待請求。

## 參數
**`PORT`** - 伺服器連線埠號,預設為 8080。
**`Stop on Error`** - 當伺服器遇到錯誤或例外時自動停止。
## Low-Code 編輯器
### options 物件
在腳本中可以直接存取 options 內建物件。options 物件中的每個 key 為工作資料夾中的一個 TXT 檔案名稱(不包含副檔名),每個 value 為該檔案的文字內容,在腳本被執行時就會自動載入所有文檔,免去於腳本中自行讀取的麻煩:
```javascript
// 讀取工作資料夾中 price.txt 的值
let price = options['price']
console.log('price:', price)
```
### input 物件
input 物件代表正要處理的 HTTP 請求,其中包含 method, path, query 以及 body 等屬性,例如請求為 GET /orders?date=2023-08-26 時,會收到 input 物件如下:
```javascript
// GET /orders?date=2023-08-26 請求的 input 物件:
{
method: 'GET',
path: '/orders',
query: {
date: '2023-08-26'
},
body: {
}
}
```
請求方可以使用 POST, PUT 等 method 並在 body 中填入 JSON 資料格式,那麼 input.body 就會是請求方帶入的 JSON 資料解析後的結果。
### output 物件
output 物件代表想要回傳給請求方的 JSON 資料格式物件,可以填入符合 JSON 物件格式的內容:
```javascript
// 填寫 output 物件:
output.timestamp = moment().format('YYYY/MM/DD HH:mm:ss')
output.orders = [
{
orderId: 1234,
items: ['coffee', 'milk']
}
}
```
模組會自動將 output 內容完整填入 HTTP 回應後送出。
### api 物件
提供同步函式:api.files(), api.read(filename, encoding='utf8'), api.write(filename, text), api.remove(filename),[moment.js ](https://momentjs.com/docs/)與 [lodash](https://lodash.com/docs/4.17.15) 也都是內建函式庫,可以直接使用。另外提供非同步函式 api.run(uuid) 可以執行獨立技能,但請注意前一個 api.run 結束後才能呼叫新的 api.run 否則會回傳例外。
為了支援可存續的資料,api.datastore() 這個同步函式會回傳一個物件,所有在這個物件內的資料當伺服器停止時將自動寫入工作資料夾的 datastore.json,並在下次啟動時自動載入:
```javascript
// 取得 datastore 物件,伺服器會自動從工作資料夾中的 datastore.json 載入
let datastore = api.datastore()
datastore.reqNum += 1
```
---
# 桌面自動化
Source: https://docs.emily.tips/wap/desktop
> EMILY.RPA 桌面自動化模組:以電腦視覺分析螢幕找出參考圖案座標,操作滑鼠與鍵盤自動化桌面應用軟體。
這個模組使用電腦視覺技術分析螢幕找出參考圖案座標,操作滑鼠與鍵盤來達成桌面應用軟體的自動化。在部署內含桌面自動化技能時,電腦螢幕設定(如解析度、顏色深度、文字放大比例等)應與訓練模式時的電腦一致,建議最好是直接在部署電腦上設計流程,並避免於執行期間操作電腦造成滑鼠與鍵盤的干擾。

## 設定權限
由於需要分析螢幕,因此第一次打開這個模組時使用者需要同意「**螢幕錄影**」的權限;另外需要控制滑鼠與鍵盤因此使用者也要同意「**輔助使用**」相關的權限。


## 注意事項
1. Windows 作業系統需要 Windows 10 64bit 以上版本,並事前安裝微軟 [VC++ 函式庫](https://docs.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170)。
2. DA 技能運作時會占用滑鼠與鍵盤,如果自動化過程中移動滑鼠或使用鍵盤,自動化的結果有可能受到影響而產生錯誤。
3. 使用者要確保輸入法(IME)的狀態與訓練時一致。有時系統對於不同的應用程式會出現輸入法自動切換,有可能導致錯誤的文字輸入。
## 訓練面板
點擊「**TRAINER**」可以啟動在桌面右上方的訓練面板,直接在本機進行桌面流程設計。當訓練面板出現後,建議將主界面與模組視窗最小化,這樣可以將空間騰出給訓練面板使用。

訓練面板分為三種模式:「**桌面**」,「**No-Code 編輯器**」,以及 「**Low-Code 編輯器**」。
**桌面模式** - 是用來直接手動調整桌面或應用程式的操作狀態,我們可以自由的將桌面調整到流程開始時所需的狀態,然後點擊快門按鈕為 No-Code 模式取得螢幕快照;也可以利用 Ctrl/Cmd+0 的快捷鍵執行快照,或是 Ctrl/Cmd+5 快捷鍵執行延遲5秒的快照。

**No-Code 編輯器** - 利用滑鼠操作帶出選單以選擇流程的新指令,然後將指令對應的程式碼寫入 Low-Code 編輯器。

**Low-Code 編輯器** - 用來手動調整 No-Code 模式產生的程式碼,以達到最大化的設計彈性。

## No-Code 編輯器
選單指令包含:「OPEN FILE」、「INPUT TEXT」、「SEND KEYS」、「SLEEP」、「COPY XY」、「CLICK LEFT」、「CLICK RIGHT」 等。其中 「OPEN FILE」 除了可以如同滑鼠雙擊指定檔案以啟動關聯的應用程式外,也可以選擇應用程式執行檔直接啟動應用程式。

例如,點選 「OPEN FILE」 新增一個指令打開會計軟體 `Accounting.app`。

當指令在 No-Code 編輯器產生後,會如下圖提醒使用者:

## Low-Code 編輯器
切換到 Low-Code 編輯器可以檢查或調整程式碼,以這個例子是剛才新增指令 「OPEN FILE」 產生的。

在訓練面板上點擊「**▶︎**」執行鍵,EMILY.RPA 就會自動切換到桌面模式並開始執行 Low-Code 程式碼,按「**■**」 停止鍵或「**Shift+ESC**」可以中斷執行。

接著可以執行一次快照,取得最新螢幕畫面後切換回 No-Code 編輯器,繼續增加下一個指令,以滑鼠拖曳螢幕畫面上的按鈕區域,放開滑鼠後帶出指令選單,選取「**CLICK CROP**」增加指令,這個指令是讓 EMILY.RPA 在螢幕找到選取的參考圖案(CROP)再進行滑鼠點擊。需要找到螢幕上指定圖案的指令都會產生參考圖案在工作資料夾,檔案命名形式為 `CROP-xxx.png`。

當指令逐漸增加後,除了訓練面板的「**▶︎**」執行鍵可以循序執行全部步驟指令外,也可以在程式碼編輯區選取想要執行的程式碼區段,點擊編輯區上方的「**RUN SELECTED CODE**」執行選取行數的程式碼,下方的範例是執行第 6 行到第 16 行。

完成 Low-Code 程式碼後,一定要記得在 Low-Code 編輯器的訓練面板點擊執行鍵左邊的「**COMMIT**」鍵。第一次點擊「**COMMIT**」程式碼會從 TRIAL 區推送到 FINAL 區,第二次點擊才會把 FINAL 區的程式碼推送回模組視窗。

最後按下「**SAVE**」 才算完成桌面自動化並儲存。如果萬一忘了儲存,可以打開訓練模式的工作資料夾,剛才在 FINAL 區的程式碼會被儲存在 code-final-xxxx.js 的檔案中:

### api.screen 物件
api.screen 提供螢幕資訊與螢幕分析相關非同步函式。
```javascript
// 取得螢幕長寬
let size = await api.screen.size()
console.log(size)
// 在螢幕上指定區域內(可忽略)尋找與指定圖檔最相似位置
let found1 = await api.screen.find('crop-1234.png', {left:0,top:0,width:600,height:600})
console.log(found1)
// 在螢幕上需找與指定圖檔有95%以上相似的所有可能位置
let found2 = await api.screen.find('crop-1234.png', {confidence:0.95, all:true})
console.log(found2)
// 最長10秒等待螢幕上指定區域(可忽略)出現與指定圖檔最相似的位置
let found3 = await api.screen.waitFor('crop-5678', 10000, {left:0,top:0,width:600,height:600,confidence:0.95})
// 從螢幕(0,0)截取長寬都是100像素的圖片
await api.screen.capture('snapshot.png', 0, 0, 100, 100)
```
### api.mouse 物件
api.mouse 提供滑鼠操作相關非同步函式。
```javascript
// 設定滑鼠控制參數:點擊間延遲/移動速度/移動段數
const msDelay = 0 // 0 ms between clicks/scrolls
const mouseSpeed = 2000 // 2000 pixels per second of moving mouse
const mouseSteps = 30 // 30 how many steps in a mouse movement
api.mouse.config(msDelay, mouseSpeed, mouseSteps)
// 移動滑鼠游標至(x,y)
await api.mouse.move(x, y)
// 取得滑鼠游標位置 {x,y}
let pos = await api.mouse.getPosition()
console.log(pos)
// 點擊滑鼠左鍵後左鍵雙擊再點擊右鍵
await api.mouse.clickLeft()
await api.mouse.doubleClick()
await api.mouse.clickRight()
// 滑鼠點擊再釋放
await api.mouse.press()
await api.mouse.release()
// 將滑鼠游標從現在位置按住左鍵拖曳到(x,y)
const button = 0 // 0:左鍵, 1:滾輪鍵, 2:右鍵
await api.mouse.drag(x, y, button)
// 操作滑鼠滾輪往:上/下/左/右
await api.mouse.scrollUp(n)
await api.mouse.scrollDown(n)
await api.mouse.scrollLeft(n)
await api.mouse.scrollRight(n)ode
```
### api.keyboard 物件
api.keyboard 提供鍵盤輸入相關非同步函式。
```javascript
// 從鍵盤發送 hello
await api.keyboard.type('hello')
// 按住與釋放按鍵
await api.keyboard.press(api.key.A)
await api.keyboard.release(api.key.A)
// 發送鍵盤常用控制鍵 ENTER/ESC/BACK/TAB
await api.keyboard.enter()
await api.keyboard.escape()
await api.keyboard.backspace()
await api.keyboard.tab()
// 發送鍵盤組合鍵 ALT+F4
await api.keyboard.keys(api.key.LeftAlt, api.key.F4)
// 發送鍵盤:全選/複製/貼上
await api.ctrlA()
await api.ctrlC()
await api.ctrlV()
```
### api 物件
提供其他簡化流程設計與操作 shell 的非同步函式。
```javascript
// 找到與crop-2345最相似位置(信心程度95%)後點擊相對位移(x,y)並等待500ms後繼續下個指令, 找到後立即移動滑鼠游標無需軌跡 (instant: true)
await api.clickCrop('crop-2345', x, y, {confidence:0.95, wait:500, instant: true})
// 找到與crop-3456最相似位置(信心程度95%)後將滑鼠游標移到相對位移(x,y)並等待500ms後再繼續下個指令
await api.moveToCrop('crop-3456', x, y, {confidence:0.95, wait:500})
// 從found3(上方範例)相對位移(x,y)擷取長寬wxh螢幕截圖做OCR
// searchLine為搜尋文字結果的正規表達式,與下方moveCursor合併使用
// moveCursor為布林值,代表是否將滑鼠游標移至找到的searchLine在螢幕上的中心位置
// language為OCR的辨識語言: 'eng','chi_tra'
let result = await api.captureToOcr(found2, x, y, w, h, searchLine, moveCursor, language)
console.log(result.text)
// 貼上文字快捷鍵
await api.pasteText('hello')
// 讀寫剪貼簿同步函式
api.clipboard.writeText('hello')
console.log(api.clipboard.readText())
// 讀CSV檔API,分隔符號為逗點,讀取表頭須從檔頭略過0列
let rows = await api.readCSV('input.csv', ',', 0)
// 寫CSV檔API,表頭依序為name,age
await api.writeCSV('output.csv', [{name:'Alice',age:20},{name:'Bob',age:25}], ['name','age'])
// 等待5秒鐘
await api.sleep(5000)
// 執行其他技能
await api.run('bed383cd-ec5b-497e-ae4d-b9ad906e0abe')
// 開啟工作資料夾檔案
await api.shell.openPath('output.csv')
// 開啟任意檔案
await api.shell.openPath('/Users/emily/Desktop/input.xlsx')
// 開啟檔案總管並選取檔案
await api.shell.showItemInFolder('/Users/emily/Desktop/input.xlsx')
// 將檔案移至資源回收桶
await api.shell.trashItem('/Users/emily/Desktop/input.xlsx')
// 開啟網頁連結
await api.shell.openExternal('https://google.com')
// 執行 PowerShell 腳本
let result1 = await api.powerShell('Get-Process')
// 執行 PowerShell PS1 檔案腳本
let result2 = await api.powerShell('./myscript.ps1')
```
提供 Desktop Use Agent 操作桌面的非同步函式。
```javascript
// 讓 AI Agent 看螢幕操作滑鼠或鍵盤達成目標,可限制最大執行步驟數,預設 10
await api.desktopUse('點擊「新增交易」按鈕', { maxActions: 10 })
```
## api.key 物件
下表為所有按鍵列表,例如空白鍵為 api.key.Space
**`Space` `Escape` `Tab` `Backspace` `Enter`**
**`LeftAlt` `RightAlt` `LeftControl` `RightControl` `LeftShift` `RightShift` `LeftSuper` `RightSuper`**
**`F1` `F2` `F3` `F4` `F5` `F6` `F7` `F8` `F9` `F10` `F11` `F12`**
**`Num0` `Num1` `Num2` `Num3` `Num4` `Num5` `Num6` `Num7` `Num8` `Num9`**
**`A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M` `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z`**
**`Grave` `Minus` `Equal` `LeftBracket` `RightBracket` `Backslash` `Semicolon` `Quote` `Comma` `Period` `Slash`**
**`Left` `Up` `Right` `Down`**
**`Print` `Pause` `Insert` `Delete` `Home` `End` `PageUp` `PageDown`**
**`NumPad0` `NumPad1` `NumPad2` `NumPad3` `NumPad4` `NumPad5` `NumPad6` `NumPad7` `NumPad8` `NumPad9`**
**`Add` `Subtract` `Multiply` `Divide` `Decimal`**
**`CapsLock` `ScrollLock` `NumLock`**
---
# 遠端桌面自動化
Source: https://docs.emily.tips/wap/rdp
> EMILY.RPA 遠端桌面自動化模組:使用 RDP 連線遠端 Windows,以電腦視覺分析螢幕找出參考圖案座標,操作滑鼠與鍵盤自動化遠端桌面應用軟體。
這個模組使用遠端桌面協定(RDP)連線至指定 IP 位址的 Windows 電腦,以電腦視覺技術分析遠端螢幕,操作遠端滑鼠與鍵盤來達成自動化。除此之外,模組也提供讀寫遠端剪貼簿文字資料與上傳或下載遠端檔案的功能,上傳下載檔案需要遠端主機啟動 SSHD 服務。
在訓練模式中,使用者可以在「**No-Code 編輯器**」連線到遠端主機,藉由功能選單生成 Low-Code 腳本或直接在「**Low-Code 編輯器**」中編寫;在執行模式中,模組會以設定好的連線資訊連接遠端主機,並自動載入執行模組儲存的 Low-Code 腳本。

## No-Code 編輯器
包含「**連線設定**」、「**連線按鈕**」、「**手動操作按鈕**」、「**螢幕畫面**」、「**狀態列**」、「**滑鼠單擊選單**」、「**滑鼠拖曳選單**」,主要是提供互動介面協助使用者產生 Low-Code 腳本。

### 連線設定 (SETTINGS)
設定遠端桌面連線資訊與 AI Agent 相關功能的金鑰與預設模型:

**`HOST/IP`** - 遠端主機的 IP 位址,可以使用 **%FILENAME%** 變數。
**`PORT`** - RDP 連線埠號,預設為常用的 3389。
**`USERNAME`** - 遠端主機的登入帳號,可以使用 **%FILENAME%** 變數。
**`PASSWORD`** - 遠端主機的登入密碼,可以使用 **%FILENAME%** 變數。
**`DOMAIN`** - 遠端主機的 Windows 網域,可以使用 **%FILENAME%** 變數。
**`RESOLUTION`** - 預設 1280x720,其他選項有 1440x900 與 1920x1080。
**`AGENT APIKEY`** - AI Agent 與 OCR 所需的金鑰,可以使用 **%FILENAME%** 變數或企業儲值的 %credit-key%。
**`AGENT MODEL`** - AI Agent 與 OCR 所需的模型。
### 
手動連線
在訓練模式下手動連線或斷線遠端主機。任何涉及遠端主機的功能只能在連線狀態下運作,包含功能選單。
### 
手動操作
在訓練模式下開啟或關閉手動操作遠端滑鼠鍵盤。模組的功能選單只能在關閉手動操作情況下運作。
### 滑鼠單擊選單
在遠端桌面螢幕上單擊滑鼠後,選單提供「**MOUSE**」、「**TYPE**」、「**SPECIAL KEY**」、「**KEY COMBINATION**」、「**CLIPBOARD**」、「**AI AGENT**」等功能來為使用者生成 Low-Code 腳本。其中 AI AGENT 相關功能會使用到連線設定中的 APIKEY 與 MODEL,也會產生相關的 Token 費用,在 DEBUG 中可以看到使用的成本。

### 滑鼠拖曳選單
在遠端桌面螢幕上拖曳滑鼠選取圖案後,選單提供「**CAPTURE CROP**」、「**CLICK AT**」、「**MOVE TO**」、「**WAIT FOR CROP**」、「**CROP TO OCR**」等功能為使用者生成參考截取圖案的 Low-Code 腳本。其中 CROP TO OCR 會使用到連線設定中的 APIKEY 與 MODEL,也會產生相關的 Token 費用,在 DEBUG 中可以看到使用的成本。

例如,拖曳滑鼠選取遠端桌面上的「**資源回收桶**」圖示後,選單選取「**CLICK AT**」後在圖示中心點擊一下,就會在 Low-Code 編輯器自動生成 Low-Code 程式碼:

## Low-Code 編輯器
Low-Code 編輯器提供腳本編輯相關功能,並提供滑鼠、鍵盤、電腦視覺、AI Agent、剪貼簿、遠端檔案傳輸與本地檔案都寫等 API,輸入 **api.** 就會出現 API 列表,需注意大多數 API 都是非同步。

### 測試執行 (TEST)
編輯完 Low-Code 腳本後,可以點擊「**TEST**」開始測試執行,並且被置換為「**STOP**」按鈕讓使用者可以中斷執行:

此時若切換到「**NO-CODE**」編輯器可以看到腳本執行的實際畫面:

如果執行測試執行部分 Low-Code 腳本,可以在「**LOW-CODE**」編輯器選取想要測試的腳本再點擊「**TEST**」:

## 傳輸檔案
Windows 提供 OpenSSH Server 的安裝,可以用管理員權限以 PowerShell 查詢,如果顯示 **Installed** 表示已安裝:
```powershell
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH.Server*'
```

如果尚未安裝,一樣可以用管理員權限以 PowerShell 安裝:
```powershell
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
```
接著用管理員權限以 PowerShell 啟動 OpenSSH Server 服務:
```powershell
Start-Service sshd
```
也可以設定為開機時自動啟動:
```powershell
Set-Service -Name sshd -StartupType Automatic
```

順利啟動 OpenSSH Server 後就可以在「**LOW-CODE**」 編輯器以 API 傳輸檔案:

---
# 個資遮蔽
Source: https://docs.emily.tips/wap/pii-redaction
> EMILY.RPA 個資遮蔽模組:將文字中的身分證、手機、地址、Email 等個資換成佔位符後再送給 LLM,取回結果後依對照表還原,明文個資不離開本機。
這個模組在本機把文字中的個資換成佔位符(placeholder),讓後續模組可以安全地把內容送給 LLM;拿回 LLM 的結果後,再用同一份對照表(map)把佔位符還原成原文。整個流程零相依、全非同步,明文個資不會隨 request 送出。

## 參數
**`FILE`** - 文字輸入檔,點擊「**PICK**」選取檔案、鍵盤輸入工作資料夾中的檔名,或使用 **%FILENAME%** 變數。`ACTION` 為 **REDACT** 時是要遮蔽的原文;為 **RESTORE** 時是 LLM 回傳、含佔位符的文字。
**`ACTION`** - 執行動作:
- **REDACT** - 偵測 `FILE` 中的個資並換成佔位符,遮蔽後文字寫入 `OUTPUT FILE`,對照表寫入 `MAP FILE`。
- **RESTORE** - 讀取 `MAP FILE`,把 `FILE` 中的佔位符還原成原文後寫入 `OUTPUT FILE`。
**`OUTPUT FILE`** - 輸出檔名,預設 `output.txt`,寫入工作資料夾。
**`MAP FILE`** - 對照表檔名,預設 `redaction-map.json`。REDACT 時產生,RESTORE 時讀取。
:::danger 對照表就是明文個資本身
`MAP FILE` 的內容存的是未經處理的明文個資,不需要還原時直接刪掉這個檔案即可。
:::
## No-Code 編輯器
點擊「**ADD NO-CODE COMMAND**」可以加入下列無程式碼指令,指令會記錄在模組的指令列表,並在執行時套用到偵測規則上:
### 加入黑名單
填入的字串**保證不會流出去**:完全比對,命中就換成 `{{BLOCKED_n}}`。適合客戶姓名、未公開的專案代號等 regex 抓不到的機敏字串。
### 加入白名單
填入的字串即使被規則命中也**不遮蔽**,例如公司對外的客服信箱、官網網址。用來壓掉已知的誤報。
:::caution
黑名單內容本身是機敏資料。技能檔若會分享給他人,先確認裡面沒有不該公開的名字。
:::
## Low-Code 編輯器
在 Low-Code 編輯器中可以直接調整偵測選項,腳本在遮蔽執行前被呼叫,適合放無法用 No-Code 表達的規則。

### input 輸入物件
```javascript
{
text // FILE 的完整文字內容
}
```
### options 選項物件
```javascript
{
patterns, // 啟用的內建規則集合,例如 ['tw', 'generic', 'financial']
rules, // 自訂規則陣列
denylist, // 黑名單,等同 No-Code 的「加入黑名單」
allowlist, // 白名單,等同 No-Code 的「加入白名單」
disable // 要關閉的內建型別,例如 ['URL']
}
```
範例:
```javascript
// 自訂員工編號規則
options.rules.push({ type: 'EMP_ID', pattern: /EMP-\d{6}/g })
// 黑名單與白名單
options.denylist.push('Best Ltd.')
options.allowlist.push('support@emily.tips')
// URL 通常不是個資,太吵就關掉
options.disable.push('URL')
```
## 內建型別
`patterns` 決定載入哪些規則集合,只啟用 `['tw']` 就真的只載入台灣規則。
| 集合 | 型別 | priority | 備註 |
|---|---|---|---|
| `tw` | `TW_ADDRESS` | 40 | 最高。地址內含數字,不然會被電話/統編咬走 |
| `tw` | `TW_ID` | 35 / 30 | 帶「身分證:」標籤的走 35 且不驗檢查碼;裸 pattern 走 30 且驗檢查碼 |
| `tw` | `TW_ARC` | 30 | 新式 `[A-Z][89]\d{8}` 與舊式 `[A-Z][A-D]\d{8}` |
| `tw` | `TW_MOBILE` | 22 | |
| `tw` | `TW_TEL` | 20 | |
| `tw` | `TW_GUI` | 15 | 裸 8 位數,誤報風險最高,檢查碼必驗 |
| `generic` | `EMAIL` | 30 | |
| `generic` | `URL` / `IPV4` | 25 | URL 常常不是個資,覺得太吵用 `disable: ['URL']` |
| `financial` | `CREDIT_CARD` / `IBAN` | 30 | Luhn / mod-97 |
| — | 自訂規則 | 50(預設) | 讓自訂勝過內建成為直覺行為 |
**地址 priority 最高**:自訂的數字規則若沒生效,先確認是不是被 `TW_ADDRESS` 蓋掉了。
`LITERAL` 與 `BLOCKED` 是保留型別,自訂規則不能使用。
## 核心不變式
```javascript
restore(redact(x).redacted, redact(x).map).text === x
```
對任意輸入、任意規則組合、任意黑名單都成立,沒有例外分支。
做得到是因為偵測跑在正規化後的文字上(全形→半形、刪零寬字元),但**替換發生在原始輸入上**,對照表存的也是原始子字串。使用者輸入 `0912-345-678` 還原後仍是 `0912-345-678`,不會被靜默改成半形。
遮蔽只有一種模式:偵測到的 span **完整置換成佔位符**。沒有 mask、沒有 format-preserving。
## 黑名單比對規則
黑名單是完全比對,比對對象是正規化後的文字(否則輸入全形公司名就抓不到),大小寫預設不敏感(只影響 ASCII,CJK 沒有大小寫概念)。
「優先級最高」的意思是保證覆蓋,不是搶佔佔位符:
| 情況 | 結果 |
|---|---|
| span 完全相同 | 黑名單勝 |
| 黑名單 span ⊃ 其他 span | 黑名單勝 |
| 部分重疊 | 黑名單勝,另一方捨棄 |
| 黑名單 span ⊂ 其他 span | **保留較大的那個** |
最後一列是刻意的。黑名單有「王小明」、地址規則抓到整串「台北市信義區信義路五段7號 王小明 收」時,若讓黑名單搶贏,結果是地址整串沒遮,優先級最高反而造成外洩。不提供「嚴格模式」,嚴格換來的是更差的保護。
沒有 `wholeWord` 選項:需要詞界的情境請用自訂規則寫 regex,CJK 沒有詞界、子字串比對是正確預設。
## 自訂規則
```javascript
options.rules.push({
type: 'CASE_NO', // 必須符合 /^[A-Z][A-Z0-9_]*$/
pattern: /案號\s*[::]\s*(?\d{6,10})/g,
priority: 60,
validate: (m) => m.value !== '000000', // 可 async
})
```
- **`redact` 具名群組**:有就只遮該群組,沒有就遮整個 match。用來處理「需要上下文才能確定,但不該把上下文一起遮掉」。
- **`g` flag 會自動補上**(沒有 g 只會抓到第一個),並發一次 warning。
- **`lastIndex` 不會殘留**:每次執行都複製一份 RegExp,同一個 rule 物件連續執行結果一致。
- **type 撞到內建型別會 fail fast**,要取代內建請把它加進 `disable`。
- **`pattern` 可以是字串**,讓規則能從 JSON 設定檔來。但**含 `validate` 的規則無法序列化**,需要驗證邏輯的必須寫在腳本裡。
## 還原與模糊比對
模型會弄壞佔位符,還原時分層處理,`maxTier` 控制放寬到哪一層:
| Tier | 處理 | 預設 |
|---|---|---|
| 1 | 完全比對 | ✓ |
| 2 | 大小寫不敏感 | ✓ |
| 3 | 全形/半形括號正規化(`{{`→`{{`)、缺一邊括號 | ✓ |
| 4 | 括號可選(`TW_ID_1` 裸寫也認) | 需明確指定 |
**編號距離 ≤1 的猜測不實作。** 把 `{{NAME_2}}` 猜成 `NAME_1` 還原成錯的人,比不還原嚴重得多,使用者會相信畫面上的內容。還原失敗的 fail-safe 是保留佔位符原樣。
還原結果的 `expected` / `matched` / `orphaned` 是統計數字,不含個資,可以安全上報:
- `matched < expected` → 模型吃掉了佔位符,應提示使用者有內容可能未正確還原
- `orphaned` 非空 → 模型自己編了一個佔位符,通常是它模仿了格式
兩個數字都在告訴你送給 LLM 的 system prompt 指示夠不夠強。
### 佔位符注入防護
輸入本身含 `{{NAME_1}}` 時(使用者貼上的,或惡意構造),還原會被輸入牽著走,是資訊洩漏。模組會把它登記成 `LITERAL` 對應回自己:
```
輸入: 我叫王小明,參考 {{NAME_1}} 這個格式
遮蔽: 我叫{{BLOCKED_1}},參考 {{LITERAL_1}} 這個格式
map: { "{{BLOCKED_1}}": "王小明", "{{LITERAL_1}}": "{{NAME_1}}" }
```
還原是**單次掃描、不遞迴**,`{{LITERAL_1}}` 還原出的 `{{NAME_1}}` 不會被第二輪再替換一次。
## 典型流程
1. 「**個資遮蔽**」模組 `ACTION` 設 **REDACT**,把使用者輸入遮蔽成 `output.txt`,對照表存 `redaction-map.json`。
2. 以 [AI Agent](/ai-agent/intro) 或其他 LLM 模組讀取 `output.txt` 產生回答。
3. 再放一個「**個資遮蔽**」模組,`ACTION` 設 **RESTORE**,`FILE` 指向 LLM 的回答檔,`MAP FILE` 用同一份 `redaction-map.json`,還原後的文字即為最終結果。
---
# 如何使用 AI Agent?
Source: https://docs.emily.tips/ai-agent/intro
> EMILY.RPA AI Agent 模組總覽:適用於網站改版、文件格式多變等動態自動化標的,並說明 Token 成本與語言模型的選擇原則。
雖然 EMILY.RPA 提供了許多 No-Code + Low-Code 的自動化模組可以應付絕大部份情況,但如果遇到會動態改變的自動化標的,例如常改版的網站、手機拍攝的文件等,就會需要可以在執行當下即時思考再採取行動的 AI Agent 模組。
由於 AI Agent 是由大型語言模型(LLM)運算驅動,因此有 GPU 的運算成本。依選擇的模型不同,輸入與輸出的 Token 單位成本也不同。模型的選擇與目標的複雜度有關,通常越複雜的目標需要越高階的模型,可以在設計階段嘗試不同品牌與版本的模型。
EMILY.RPA 提供使用者以自己申請的 API Key 來驅動 Agent 或跟 EMILY.RPA 採購儲值來扣抵每次執行的成本。透過 EMILY.RPA 儲值就能使用企業級 API Key,具有模型商零資料保存(Zero Data Retention)與優先存取的保證,並能在不同模型供應商之間無縫轉換,自動依照各模型牌價扣抵餘額,毋需綁定信用卡。
---
# ChatGPT
Source: https://docs.emily.tips/ai-agent/chatgpt
> EMILY.RPA ChatGPT 模組:呼叫 OpenAI GPT 模型,輸入文本提示 (Prompt) 與影像檔案,將結果輸出至工作資料夾的 output.txt。
使用 OpenAI 的 GPT 模型,輸入自然語言型態的文本提示(Prompt)與影像檔案,輸出文本結果至工作資料夾中的 output.txt 檔案。

## 參數
**`API KEY`** - 使用 OpenAI 模型的 API 金鑰。可以使用 **%FILENAME%** 變數,或使用儲值的專用金鑰 **%credit-key%**。
**`MODEL`** - 預設為 gpt-4o 模型,可下拉選擇其他模型或自行輸入。
**`IMAGE`** - 可選擇一個影像檔讓模型分析。
**`OUTPUT`** - 輸出可選擇純文本或 JSON 格式。
**`TEMPERATURE(0~1.0)`** - 回應的隨機度,0 為最低最穩定,1.0 為最隨機。
**`MAX TOKENS`** - 限制最高回應字詞數,通常給越高值需要越多時間生成回應。
**`SYSTEM PROMPT`** - 指定給模型的角色或輸出指引,可以使用 **%FILENAME%** 樣板。
**`USER PROMPT`** - 使用者提示與輸入,可以使用 **%FILENAME%** 樣板。
## 模型限制與價格
GPT 各個模型的特色、功能,限制與價格可以參考 [OpenAI 官網](https://platform.openai.com/docs/models)。
---
# Gemini
Source: https://docs.emily.tips/ai-agent/gemini
> EMILY.RPA Gemini 模組:呼叫 Google Gemini 模型,輸入文本提示 (Prompt) 與影像檔案,將結果輸出至工作資料夾的 output.txt。
使用 Google 的 Gemini 模型,輸入自然語言型態的文本提示(Prompt)與影像檔案,輸出文本結果至工作資料夾中的 output.txt 檔案。

## 參數
**`API KEY`** - 使用 Gemini 模型的 API 金鑰。可以使用 **%FILENAME%** 變數,或使用儲值的專用金鑰 **%credit-key%**。
**`MODEL`** - 預設為 gemini-2.5-flash 模型,往後若有新模型發佈可以置換。
**`IMAGE`** - 可選擇一個影像檔讓模型分析。
**`OUTPUT`** - 輸出可選擇純文本或 JSON 格式。
**`TEMPERATURE(0~1.0)`** - 回應的隨機度,0 為最低最穩定,1.0 為最隨機。
**`MAX TOKENS`** - 限制最高回應字詞數,通常給越高值需要越多時間生成回應。
**`SYSTEM PROMPT`** - 指定給模型的角色或輸出指引,可以使用 **%FILENAME%** 樣板。
**`USER PROMPT`** - 使用者提示與輸入,可以使用 **%FILENAME%** 樣板。
## 模型限制與價格
Gemini 各個模型的特色、功能,限制與價格可以參考 [Gemini 官網](https://ai.google.dev/gemini-api/docs/pricing)。
---
# Browser Use Agent
Source: https://docs.emily.tips/ai-agent/browser-use-agent
> EMILY.RPA Browser Use Agent 模組:以自然語言描述任務目標,由大型語言模型自主操作瀏覽器完成網頁任務。
Browser Use Agent 以自然語言描述任務目標,並透過大型語言模型(LLM)自主操作瀏覽器。需注意越大的目標語言模型越容易產生誤判,也會使用更多的 Token,建議拆解成多個小任務來降低失敗率。如果不熟悉如何提示語言模型達成任務目標,可以善用「**Ask EMILY**」讓 AI 生成友善語言模型的目標提示。

## 參數
**`API KEY`** - OpenAI 或 Google 的 API 金鑰,支援 **%FILENAME%** 變數,或使用儲值的專用金鑰 **%credit-key%**。
* OpenAI API Key 請參閱 [OpenAI 金鑰申請](/faq/apply-openai-key)
* Google API Key 請參閱 [Gemini 金鑰申請](/faq/apply-gemini-key)
**`MODEL`** - 目前支援以下模型:
| 平台 | 模型 | 價格 |
| --------- | ----------------------------------------------------------------------------- | ------------------------------------------------------ |
| OpenAI | gtp-5, gpt-5-mini, gpt-4.1, gpt-4.1-mini, computer-use | [OpenAI 官網](https://platform.openai.com/docs/models) |
| Google | gemini-3-pro, gemini-3-flash, gemini-2.5-pro, gemini-2.5-flash, computer-use | [Gemini 官網](https://ai.google.dev/gemini-api/docs/pricing) |
| Anthropic | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5, computer-use | [Anthropic 官網](https://docs.anthropic.com/en/docs/about-claude/models) |
**`MAX ACTION`** - 設定代理最多可執行的動作次數,範圍為 1–100。
**`GUARDRAIL`** - 設定代理的操作範圍限制:
* `SAME PAGE` - 僅限目前網頁
* `SAME SITE` - 僅限同一網域中的網頁
* `NONE` - 沒有限制
> 因為使用模型會依使用量計費,建議適當的設定 **`MAX ACTION`** 與 **`GUARDRAIL`** 參數來避免預期外的花費。
**`GOAL`** - 用自然語言描述任務,可使用 **%FILENAME%** 樣板。
**`ACTION`** - 由模型判斷並執行的下一步瀏覽器操作。每個步驟都會自動擷取螢幕畫面,並儲存至工作資料夾中以供追蹤與檢視。
## 範例
以這個查詢高鐵班車時刻為例,查詢網頁預設從「南港」出發抵達「左營」,日期是 2026/01/26,時間為 20:30。

使用自然語言提示模型:查詢 2026/01/30 早上九點後,從「台北」出發到「台南」的班車。然後點擊「**TEST**」執行看看。

最後檢查瀏覽器中的內容是否正確。

---
# Web Read Agent
Source: https://docs.emily.tips/ai-agent/web-read-agent
> EMILY.RPA Web Read Agent 模組:以大型語言模型擷取網頁 (HTML) 中的資訊,並將結果輸出至工作資料夾文檔。
Web Read Agent 使用大型語言模型(LLM)擷取網頁(HTML)中的資訊,並將結果輸出至工作資料夾的文檔。如果不熟悉如何提示語言模型達成任務目標,可以善用「**Ask EMILY**」讓 AI 生成友善語言模型的目標提示。

## 參數
**`API KEY`** - OpenAI 或 Google 的 API 金鑰,支援 **%FILENAME%** 變數,或使用儲值的專用金鑰 **%credit-key%**。
* OpenAI API Key 請參閱 [OpenAI 金鑰申請](/faq/apply-openai-key)
* Google API Key 請參閱 [Gemini 金鑰申請](/faq/apply-gemini-key)
**`MODEL`** - 目前支援以下模型:
| 平台 | 模型 | 價格 |
| ------ | --------------------------------------------------------------- | ------------------------------------------------------ |
| OpenAI | gtp-5, gpt-5-mini, gpt-4.1, gpt-4.1-mini | [OpenAI 官網](https://platform.openai.com/docs/models) |
| Google | gemini-3-pro, gemini-3-flash, gemini-2.5-pro, gemini-2.5-flash | [Gemini 官網](https://ai.google.dev/gemini-api/docs/pricing) |
| Anthropic | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5 | [Anthropic 官網](https://docs.anthropic.com/en/docs/about-claude/models) |
**`HTML`** - 輸入的 HTML 檔。點擊「**PICK**」選取檔案,或使用 **%FILENAME%** 變數,如果留空代表使用目前 EMILY 瀏覽器中的網頁。
### ADD PROMPT
加入自然語言提示詞來告訴模型擷取網頁中的資訊。**`FILENAME`** 用來指定寫入的工作資料夾檔案。**`PROMPT`** 則是提示模型擷取網頁中什麼資訊。

## 範例
以 Google Finance 網站為例,目標是擷取網頁中輝達股價的漲幅,因此先以網頁自動化載入 `https://www.google.com/finance/quote/NVDA:NASDAQ`

Web Read Agent 模型選擇 Google/gemini-2.5-flash 加入一個提示,檔名是 stock,提示內容是:輝達今天的漲幅是幾個百分點?

最後可以點擊「**TEST**」測試看看,然後檢查工作資料夾中 stock.txt 內容是否正確。

---
# Document Read Agent
Source: https://docs.emily.tips/ai-agent/document-read-agent
> EMILY.RPA Document Read Agent 模組:以大型語言模型擷取 PDF 等文件中的資訊並輸出至工作資料夾,GPT 以文本分析、Gemini 以圖像分析處理 PDF。
Document Read Agent 使用大型語言模型(LLM)擷取文件中的資訊,並將結果輸出至工作資料夾的文檔。GPT 模型在解析 PDF 檔案中文本資料是採取文本分析,而 Gemini 模型則是將 PDF 檔案中所有資料都視為圖像分析。如果不熟悉如何提示語言模型達成任務目標,可以善用「**Ask EMILY**」讓 AI 生成友善語言模型的目標提示。

## 參數
**`API KEY`** - OpenAI 或 Google 的 API 金鑰,支援 **%FILENAME%** 變數,或使用儲值的專用金鑰 **%credit-key%**。
* OpenAI API Key 請參閱 [OpenAI 金鑰申請](/faq/apply-openai-key)
* Google API Key 請參閱 [Gemini 金鑰申請](/faq/apply-gemini-key)
**`MODEL`** - 目前支援以下模型:
| 平台 | 模型 | 價格 |
| ------ | --------------------------------------------------------------- | ------------------------------------------------------ |
| OpenAI | gtp-5, gpt-5-mini, gpt-4.1, gpt-4.1-mini | [OpenAI 官網](https://platform.openai.com/docs/models) |
| Google | gemini-3-pro, gemini-3-flash, gemini-2.5-pro, gemini-2.5-flash | [Gemini 官網](https://ai.google.dev/gemini-api/docs/pricing) |
| Anthropic | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5 | [Anthropic 官網](https://docs.anthropic.com/en/docs/about-claude/models) |
**`PDF/DOCX/TXT/PNG/JPG/GOOGLEDOC`** - 輸入的文件檔。點擊「**PICK**」選取檔案,或使用 **%FILENAME%** 變數。除了左列的文件格式檔案外,也支援 **Google Docs ID**。
### ADD PROMPT
加入自然語言提示詞來告訴模型擷取網頁中的資訊。**`FILENAME`** 用來指定寫入的工作資料夾檔案。**`PROMPT`** 則是提示模型擷取網頁中什麼資訊。

## 範例
以台積電的財報為例,目標是擷取 114 年第一季的營收。

Document Read Agent 模型選擇 `Google/gemini-2.5-flash`,加入一個提示,檔名是 `revenue`,內容是 `台積電114年第一季營收`。

最後點擊「**TEST**」測試看看,然後檢查工作資料夾中 `revenue.txt` 內容是否正確。

---
# Table Read Agent
Source: https://docs.emily.tips/ai-agent/table-read-agent
> EMILY.RPA Table Read Agent 模組:以大型語言模型擷取表格中的資訊,並將結果輸出至工作資料夾文檔。
Document Read Agent 使用大型語言模型(LLM)擷取表格中的資訊,並將結果輸出至工作資料夾的文檔。如果不熟悉如何提示語言模型達成任務目標,可以善用「**Ask EMILY**」讓 AI 生成友善語言模型的目標提示。

## 參數
**`API KEY`** - OpenAI 或 Google 的 API 金鑰,支援 **%FILENAME%** 變數,或使用儲值的專用金鑰 **%credit-key%**。
* OpenAI API Key 請參閱 [OpenAI 金鑰申請](/faq/apply-openai-key)
* Google API Key 請參閱 [Gemini 金鑰申請](/faq/apply-gemini-key)
**`MODEL`** - 目前支援以下模型:
| 平台 | 模型 | 價格 |
| ------ | --------------------------------------------------------------- | ------------------------------------------------------ |
| OpenAI | gtp-5, gpt-5-mini, gpt-4.1, gpt-4.1-mini | [OpenAI 官網](https://platform.openai.com/docs/models) |
| Google | gemini-3-pro, gemini-3-flash, gemini-2.5-pro, gemini-2.5-flash | [Gemini 官網](https://ai.google.dev/gemini-api/docs/pricing) |
| Anthropic | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5 | [Anthropic 官網](https://docs.anthropic.com/en/docs/about-claude/models) |
**`XLSX/CSV/TSV/GOOGLESHEET`** - 輸入的文件檔。點擊「**PICK**」選取檔案,或使用 **%FILENAME%** 變數。除了左列的文件格式檔案外,也支援 **Google Sheets ID**。
**`SHEET`** - 輸入工作表名稱,留空代表為檔案中的第一個工作表。
### ADD PROMPT
加入自然語言提示詞來告訴模型擷取網頁中的資訊。**`FILENAME`** 用來指定寫入的工作資料夾檔案。**`PROMPT`** 則是提示模型擷取網頁中什麼資訊。

## 範例
以下列銷售紀錄表為例,目標是找出總金額大於 50,000 的交易。

Table Read Agent 模型選擇 `OpenAI/gpt-4.1`,加入一個提示,檔名是 result.txt,提示是:找出「銷售金額合計」大於「50,000」的資料,以物件陣列輸出。

最後點擊「**TEST**」測試看看,然後檢查工作資料夾中 `result.txt` 內容是否正確。

---
# Table Write Agent
Source: https://docs.emily.tips/ai-agent/table-write-agent
> EMILY.RPA Table Write Agent 模組:以自然語言描述任務目標,由大型語言模型自主編輯指定表格中的資訊。
Table Write Agent 使用自然語言描述任務目標,並透過大型語言模型(LLM)自主編輯指定表格中的資訊。需注意越大的目標語言模型越容易產生誤判,也會使用更多的 Token,建議拆解成多個小任務來降低失敗率。如果不熟悉如何提示語言模型達成任務目標,可以善用「**Ask EMILY**」讓 AI 生成友善語言模型的目標提示。

## 參數
**`API KEY`** - OpenAI 或 Google 的 API 金鑰,支援 **%FILENAME%** 變數,或使用儲值的專用金鑰 **%credit-key%**。
* OpenAI API Key 請參閱 [OpenAI 金鑰申請](/faq/apply-openai-key)
* Google API Key 請參閱 [Gemini 金鑰申請](/faq/apply-gemini-key)
**`MODEL`** - 目前支援以下模型:
| 平台 | 模型 | 價格 |
| ------ | --------------------------------------------------------------- | ------------------------------------------------------ |
| OpenAI | gtp-5, gpt-5-mini, gpt-4.1, gpt-4.1-mini | [OpenAI 官網](https://platform.openai.com/docs/models) |
| Google | gemini-3-pro, gemini-3-flash, gemini-2.5-pro, gemini-2.5-flash | [Gemini 官網](https://ai.google.dev/gemini-api/docs/pricing) |
| Anthropic | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5 | [Anthropic 官網](https://docs.anthropic.com/en/docs/about-claude/models) |
**`XLSX/CSV/TSV/GOOGLESHEET`** - 輸入的文件檔。點擊「**PICK**」選取檔案,或使用 **%FILENAME%** 變數。除了左列的文件格式檔案外,也支援 **Google Sheets ID**。
**`SHEET`** - 輸入工作表名稱,留空代表為檔案中的第一個工作表。
**`MAX ACTION`** - 設定代理最多可執行的動作次數,範圍為 1–100。
**`GOAL`** - 用自然語言描述任務,可使用 **%FILENAME%** 樣板。
**`STATUS`** - 由模型判斷並執行的下一步表格操作。
## 範例
以下列銷售明細表為例,任務是將修改符合條件的銷售日期。

匯入銷售明細表格檔案到工作資料夾。

Table Write Agent 模型選擇 `Google/gemini-2.5-flash`,並將剛才匯入的表格檔名填入參數,利用自然語言提示模型:將銷售日期為 7 號的資料都改為 8 號。

最後點擊「**TEST**」測試看看,然後檢查工組資料夾中 `sales.xlsx` 內容是否正確。

---
# File System Agent
Source: https://docs.emily.tips/ai-agent/file-system-agent
> EMILY.RPA File System Agent 模組:以自然語言描述任務目標,由大型語言模型自主操作指定資料夾,包括讀取、寫入與刪除檔案。
File System Agent 使用自然語言描述任務目標,並透過大型語言模型(LLM)自主操作檔案系統指定資料夾,包括讀取、寫入、刪除檔案等。需注意越大的目標語言模型越容易產生誤判,也會使用更多的 Token,建議拆解成多個小任務來降低失敗率。如果不熟悉如何提示語言模型達成任務目標,可以善用「**Ask EMILY**」讓 AI 生成友善語言模型的目標提示。

## 參數
**`API KEY`** - OpenAI 或 Google 的 API 金鑰,支援 **%FILENAME%** 變數,或使用儲值的專用金鑰 **%credit-key%**。
* OpenAI API Key: 請參閱 [OpenAI 金鑰申請](/faq/apply-openai-key)
* Google API Key: 請參閱 [Gemini 金鑰申請](/faq/apply-gemini-key)
**`MODEL`** - 目前支援以下模型:
| 平台 | 模型 | 價格 |
| ------ | --------------------------------------------------------------- | ------------------------------------------------------ |
| OpenAI | gtp-5, gpt-5-mini, gpt-4.1, gpt-4.1-mini | [OpenAI 官網](https://platform.openai.com/docs/models) |
| Google | gemini-3-pro, gemini-3-flash, gemini-2.5-pro, gemini-2.5-flash | [Gemini 官網](https://ai.google.dev/gemini-api/docs/pricing) |
| Anthropic | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5 | [Anthropic 官網](https://docs.anthropic.com/en/docs/about-claude/models) |
**`FOLDER PATH`** - 目標資料夾路徑。可以點擊「**PICK**」選取檔案,或使用 **%FILENAME%** 變數。
**`MAX ACTION`** - 設定代理最多可執行的動作次數,範圍為 1–100。
**`GOAL`** - 用自然語言描述任務,可使用 **%FILENAME%** 樣板。
**`STATUS`** - 由模型判斷並執行的下一步檔案系統操作。
## 範例
以下列資料夾為例,任務是將訂單檔案壓縮成 ZIP 格式並儲存在「訂單歸檔」資料夾。

File System Agent 模型選擇 `Google/gemini-2.5-flash`,利用自然語言提示模型:將採購訂單檔案壓縮成 order.zip 輸出到「訂單歸檔」資料夾。

最後點擊「**TEST**」測試看看,然後檢查目標資料夾中 `訂單歸檔/order.zip` 內容是否正確。

---
# Agentic Workflow
Source: https://docs.emily.tips/ai-agent/agentic-workflow
> EMILY.RPA Agentic Workflow 模組:以自然語言描述任務目標,由大型語言模型自主規劃流程步驟,可操作瀏覽器、存取工作資料夾檔案、寄送郵件與撰寫程式碼。
Agentic Workflow 以自然語言描述任務目標,並透過大型語言模型(LLM)自主規劃流程步驟,可自行操作瀏覽器,存取工作資料夾中的檔案,寄信給綁定 EMILY 的電子郵件帳號,以及撰寫程式碼來完成目標。需注意越大的目標語言模型越容易產生誤判,也會使用更多的 Token,建議拆解成多個小任務來降低失敗率。如果不熟悉如何提示語言模型達成任務目標,可以善用「**Ask EMILY**」讓 AI 生成友善語言模型的目標提示。

## 參數
**`API KEY`** - OpenAI / Google / Anthropic 的 API 金鑰,支援 **%FILENAME%** 變數,或使用儲值的專用金鑰 **%credit-key%**。
* OpenAI API Key 請參閱 [OpenAI 金鑰申請](/faq/apply-openai-key)
* Google API Key 請參閱 [Gemini 金鑰申請](/faq/apply-gemini-key)
* Anthropic API Key 請參閱 [Anthropic 金鑰申請](/faq/apply-anthropic-key)
**`MODEL`** - 目前支援以下模型:
| 平台 | 模型 | 價格 |
| --------- | ----------------------------------------------------------------------------- | ------------------------------------------------------ |
| OpenAI | gtp-5.4, gpt-5.4-mini | [OpenAI 官網](https://platform.openai.com/docs/models) |
| Google | gemini-3-flash, gemini-3.1-pro, gemini-3-flash | [Gemini 官網](https://ai.google.dev/gemini-api/docs/pricing) |
| Anthropic | claude-opus-4-6, claude-sonnet-4-6 | [Anthropic 官網](https://docs.anthropic.com/en/docs/about-claude/models) |
**`BUDGET`** - 任務預算,以美元計價,一旦超過預算就中止任務。
**`COST`** - 實際任務花費,以美元計價,測試執行或正式執行會動態更新。
**`SANDBOX`** - 沙盒設定。Agent 本身已被限制只能存取內建瀏覽器與工作資料夾,可進一步限制禁止存取的網頁或工作資料夾中的檔案。
**`SKILLS`** - 任務中可呼叫的子技能,子技能應充分描述功能、使用時機、與輸入輸出檔案。
**`MISSION`** - 用自然語言描述任務,可使用 **%FILENAME%** 樣板。
## 範例
以這個查詢專利為例,任務內容要清楚描述從哪個網站以什麼條件查詢資料,輸出的檔案格式,以及需達成的目標:

企業對資料保密有特殊要求可以點擊「**SANDBOX**」設定禁止前往的網頁與工作資料夾檔案的黑名單:

而需要可預期結果的(Deterministic)操作或機敏檔案的處理可以改以RPA執行,以子技能(SKILL)方式提供給 Agentic Workflow 呼叫,點擊「**SKILLS**」新增:

---
# Exchange Online 存取設定
Source: https://docs.emily.tips/faq/config-exchange-online
> EMILY.RPA 存取 Exchange Online 的設定步驟:取得租用戶識別碼 (Tenant ID)、應用程式識別碼與用戶端密碼。
# Exchange Online 存取設定
### 租用戶識別碼 TENANT ID
使用 Microsoft 帳號在 Azure Portal 搜尋並進入 Azure Active Directory (現改為 Microsoft Entra ID) 概觀,就可以看到 `租用戶識別碼`。

### 用戶端識別碼 CLIENT ID
要存取 Exchange Onine 前,需要新增一個「**應用程式註冊**」 CLIENT ID 是上述的租用戶中新增註冊的企業應用程式 `用戶端識別碼`。註冊步驟如下:

名稱取與用途相符比較容易理解,支援的帳戶類型保留預設單一租用戶 `僅此組織目錄中的帳戶` 即可,除非有其他租用戶也希望用這個用戶端來存取郵件。平台設定為 `Web`,URI 設定為 `http://localhost:3650/callback`

點擊「**註冊**」後可以複製用戶端識別碼。

### 用戶端密碼 CLIENT SECRET
接著繼續點擊上圖中的「**新增憑證或秘密**」,在「**新增用戶端密碼**」頁填寫 `描述` 並選擇 `到期`,建議選長一點的到期日,避免到期後要再新增一組用戶端密碼。

按「**新增**」後可以複製「**用戶端密碼**」的值。

---
# OpenAI 金鑰申請
Source: https://docs.emily.tips/faq/apply-openai-key
> 申請 OpenAI API 金鑰的步驟,供 EMILY.RPA 的 ChatGPT 模組與 AI Agent 使用。
# OpenAI 金鑰申請
先至 OpenAI 網站 ([https://platform.openai.com/](https://platform.openai.com/)) 申請帳號。

接著左側欄選「**API keys**」進入頁面產生金鑰,複製到剪貼簿即可。

---
# Gemini 金鑰申請
Source: https://docs.emily.tips/faq/apply-gemini-key
> 在 Google AI Studio 申請 Gemini API 金鑰的步驟,供 EMILY.RPA 的 Gemini 模組與 AI Agent 使用。
先至 [Google AI Studio 官網](https://aistudio.google.com/) 註冊或登入 Google 帳號後。

接著左側欄選「**Get API key**」進入頁面產生金鑰,複製到剪貼簿即可。

---
# Anthropic 金鑰申請
Source: https://docs.emily.tips/faq/apply-anthropic-key
> 申請 Anthropic API 金鑰的步驟,供 EMILY.RPA 的 AI Agent 使用 Claude 模型。
# Anthropic 金鑰申請
先至 Anthropic 網站 ([https://platform.claude.com/](https://platform.claude.com/)) 申請帳號。

接著左側欄選「**Dashboard**」進入頁面產生金鑰,複製到剪貼簿即可。

---
# 如何管理與稽核?
Source: https://docs.emily.tips/manage/intro
> EMILY.RPA 部署後的兩種管理與稽核方式:群組與全自管伺服器。
在部署機器人與技能後後 EMILY.RPA 提供兩種方式可以持續管理與稽核:[群組](/docs/manage/group.md)與[全自管伺服器](/docs/manage/server.md)。
---
# 群組
Source: https://docs.emily.tips/manage/group
> EMILY.RPA 群組功能:集中管理多個帳號、技能與授權,並提供依時間排序的使用紀錄供稽核。
群組可以管理一個以上的 EMILY.RPA 帳號,以及帳號相關的技能與授權,同時提供依時間排序的使用紀錄。

## 登入
群組的管理後台可以從[群組入口](https://emily.tips/page/login-dashboard)登入。在設定群組時需要群組名稱 `GROUP` 與管理員電子信箱地址,名稱通常以網域名稱作為區別,管理員電子信箱地址可以設定多組。

在 EMILY.PRA 服務團隊設定完成後,第一次進入群組入口時填入群組名稱,然後點擊「**Forgot Password**」,就會發送一封重設群組密碼的郵件到設定的管理員信箱。

收到重設群組密碼信件後,點擊信件中連結可以重新設定密碼,同時需要信件中的 **PIN**。往後就只需要從群組入口以新密碼進入。

## 使用者帳號管理
將左上方「**VIEW**」切換為 `USER`,然後可以在右上方快搜 SEARCH 輸入使用者帳號的局部字段,例如:jerry 就能搜尋到 jerry@emily.tips 這個帳號。

以下說明各項對使用者帳號的管理功能。
### EXIT GROUP
將指定帳號退群。
### EXPORT
將指定帳號的使用授權匯出,會存放在「**VIEW**」為 `LICENSE` 的授權管理頁面。
### SESSION
將指定帳號的指定登入連線刪除,通常是該使用者在第一台電腦開啟 EMILY.RPA 後沒有關閉,又在第二台電腦開啟,就會被提示「超過授權電腦數量」,可以在這裡刪除第一台電腦的登入連線「Jerry@MBP4(3.8.20260128)」,第二台電腦就能開啟進入。

### EXECUTABLE
設定指定帳號是否可以執行技能。
### TRAINER
設定指定帳號是否可以設計技能。
### TRIGGER
設定指定帳號是否可以使用各種全自動觸發。
### VIEW LOG
檢視指定帳號的使用紀錄,最長可以瀏覽過去一個月資料。
## 技能管理
管理員可以透過技能管理設定哪些使用者可以看到哪些技能。

## 授權管理
管理員可以瀏覽發予這個群組的所有授權,對沒有被啟用的授權(使用者欄位為空)可以下載,提供給使用者啟用。

## 使用紀錄
管理員可以下載群組每日的使用紀錄,格式為CSV。

## 儲值餘額
群組可以儲值用來扣抵 AI Agent 的使用,以美元計價。

## 帳密管理
管理員可以設定多個帳密變數,例如客服郵件信箱密碼或 API key,使用者以 **%VAR%** 方式使用,但看不到變數內容,避免使用者將帳密外洩。例如下圖,建立一個 `gemini-key` 的變數讓使用者在 EMILY.RPA AI Agent 中的 API key 填入 `%gemini-key%`。

## 其它設定
管理員可以自訂系統發送通知信的主旨與內文。
---
# 全自管伺服器
Source: https://docs.emily.tips/manage/server
> EMILY.RPA 全自管伺服器:在企業自有機房部署獨立的授權伺服器與機器人,可完全與外網斷開運行。
EMILY.RPA 提供全自管伺服器的方案,讓企業可以在自己的機房裡部署獨立的流程自動化服務,取代官方伺服器 https://emily.tips 執行使用者帳號認證與授權。
這個服務包含了一個授權伺服器與機器人應用程式,伺服器授權可同時連線的機器人數量(concurrent robot),運行時可以完全與外網斷開,可以進一步確保資訊不外流。伺服器可以在 Windows Server 2016 以上、Mac OS 11 或主流 Linux 的伺服器上運行,機器人應用程式則與官網提供的下載版本一致。
---
# 第三方軟體、套件、開源碼
Source: https://docs.emily.tips/announce/third-party-notice
> EMILY.RPA 使用的第三方軟體、套件與開源碼授權條款清單。
- [@nut-tree/nut.js](https://github.com/nut-tree/nut.js/blob/d4ca59a9cc68fdf224aa990b572f05ff2881c264/LICENSE)
- [expressjs/express](https://github.com/expressjs/express/blob/master/LICENSE)
- [expressjs/body-parser](https://github.com/expressjs/body-parser)
- [expressjs/cookie-parser](https://github.com/expressjs/cookie-parser/blob/master/LICENSE)
- [runk/node-chardet](https://github.com/runk/node-chardet)
- [kelektiv/node-cron](https://github.com/kelektiv/node-cron/blob/master/LICENSE)
- [mafintosh/csv-parser](https://github.com/mafintosh/csv-parser/blob/master/LICENSE)
- [adaltas/node-csv-stringify](https://csv.js.org/project/license)
- [data-uri/datauri](https://github.com/data-uri/datauri/blob/main/MIT-LICENSE.txt)
- [yuanchuan/find](https://github.com/yuanchuan/find/blob/master/LICENSE)
- [iprichardson/node-fs-extra](https://github.com/jprichardson/node-fs-extra/blob/master/LICENSE)
- [ashtuchkin/iconv-lite](https://github.com/ashtuchkin/iconv-lite/blob/master/LICENSE)
- [image-js](https://github.com/image-js/image-js/blob/legacy/LICENSE)
- [chadxz/imap-simple](https://github.com/chadxz/imap-simple/blob/master/LICENSE-MIT)
- [lodash](https://github.com/lodash/lodash/blob/master/LICENSE)
- [log4js-node](https://github.com/log4js-node/log4js-node/blob/master/LICENSE)
- [nodemailer/mailparser](https://github.com/nodemailer/mailparser/blob/master/LICENSE)
- [jshttp/mime-types](https://github.com/jshttp/mime-types/blob/master/LICENSE)
- [moment](https://github.com/moment/moment/blob/develop/LICENSE)
- [expressjs/multer](https://github.com/expressjs/multer/blob/master/LICENSE)
- [electron](https://github.com/electron/electron/blob/main/LICENSE)
- [sidorares/node-mysql2](https://github.com/sidorares/node-mysql2/blob/master/License)
- [nodemailer](https://github.com/nodemailer/nodemailer/blob/master/LICENSE)
- [oracle/node-oracledb](https://github.com/oracle/node-oracledb/blob/main/LICENSE.md)
- [brianc/node-postgres](https://github.com/brianc/node-postgres/blob/master/LICENSE)
- [eugeneware/replacestream](https://github.com/eugeneware/replacestream/blob/master/LICENSE)
- [parshap/node-sanitize-filename](https://github.com/parshap/node-sanitize-filename/blob/master/LICENSE.md)
- [uuidjs/uuid](https://github.com/uuidjs/uuid/blob/master/LICENSE.md)
- [sheetjs](https://github.com/SheetJS/sheetjs/blob/master/LICENSE)