🐬Spotfire Automation Services 能不能正常匯出報表?一篇搞懂「為什麼同一台機器也會失敗」與必做檢查清單

前言:我明明在 Spotfire 裡按一下就能匯出,為什麼放到 Automation Services 就不行?

很多人第一次把 Spotfire 的 IronPython 腳本丟進 Automation Services 排程時,會遇到這種崩潰情境:

  • 在電腦上用 Spotfire Analyst 手動跑:正常匯出 PDF/CSV

  • 放到 Automation Services 上排程跑:沒檔案、報錯、或跑完但什麼都沒產出

更常見的誤解是:

「Automation 與 Server 在同一台機器,應該就一定能存檔吧?」

答案是:不一定
因為 Automation Services 的腳本不是用「你在桌面操作 Spotfire 的那個使用者」在跑,而是用 伺服器服務帳號(Service Account) 在背景執行。
同一台機器只代表「磁碟路徑存在」,不代表它有權限寫入、也不代表 資料庫連線方式相同


Spotfire Automation Services 在做什麼?(給完全新手的比喻)

你可以把它想成:

  • 你在桌面點 Spotfire 匯出報表:像是「你本人拿著筆電親自操作」

  • Automation Services 排程跑:像是「公司派了一個機器人,半夜自動打開檔案、刷新資料、匯出報表」

重點是:
機器人不是你本人,它有自己的通行證(帳號/權限)
所以只要「通行證」權限不足,它就會:

  • 建不了資料夾

  • 寫不了檔案

  • 連不上資料庫

  • 找不到你指定的頁面/視覺化元件


為什麼「同一台 Server」也會失敗?5 個最常見原因

1) 檔案寫入權限不足(最常見)

Automation Services 以 Windows Service 身分跑。
你在桌面能寫入 C:\某資料夾,不代表服務帳號也能寫入。

典型症狀

  • Job 顯示成功/完成,但資料夾裡沒有任何檔案

  • 或 log 出現 access denied / unauthorized / cannot create directory

✅ 解法(概念)

  • 把輸出路徑改到「明確授權」的資料夾

  • 或對 Automation 的 service account 開放寫入權限


2) 你在腳本中用「頁面索引」或「標題名稱」硬找視覺化元件,容易失效

很多腳本會寫成:

  • 用第幾頁(Page[3])

  • 用 Visual Title 精準比對(例如完全相同字串)

但只要有人:

  • 插入一個新頁面、調整順序

  • 改了圖表標題

  • 多了一個空白或換行

就可能導致 Automation 找不到圖表 → 後面匯出直接失敗。

✅ 解法(概念)

  • 優先用 Page Name(頁面名稱)找

  • Visual 的比對採「包含/前綴」更耐用

  • 找不到就立刻丟錯(讓 log 清楚)


3) 資料庫連線身分不一致(你手動 OK,排程不 OK)

桌面測試時,可能用的是你自己的登入憑證;
排程跑時,可能用的是伺服器帳號或儲存的資料來源設定。

典型症狀

  • Analyst 可以看到資料,Automation 刷新後資料變空

  • 或直接連線失敗、權限不足

✅ 解法(概念)

  • 確認 Automation 使用的 Data Source 是 server-side 可用

  • 確認 service account 有權限使用該資料來源/資料庫


4) 路徑字串寫法不安全(跳脫字元陷阱)

很多人會直接寫 C:\temp\report\...,在某些情境會遇到跳脫字元或組字錯誤。

✅ 解法(概念)

  • 使用「安全組路徑」的方法(例如 .NET 的 Path.Combine 思路)

  • 避免手刻大量反斜線


5) 沒有「失敗就中止」與「清楚 log」→ 看起來像成功,其實是悄悄失敗

如果腳本只是 print 一些東西、沒有 try/except,也沒有在關鍵步驟檢查回傳值,Automation 常常會出現:

  • Job 看似跑完

  • 但其中某一步失敗後沒有終止

  • 最後什麼都沒輸出,難以追查

✅ 解法(概念)

  • 關鍵步驟一定要加上「找不到就丟錯」

  • 並寫清楚 log(包含輸出路徑、篩選條件、匯出檔名)


Automation 友善的「匯出 CSV + PDF」範例

目的在教新手:如何做「安全路徑、找不到就中止、寫清楚 log」。


# (示範用) Automation 匯出流程骨架:建立輸出資料夾 -> 套用條件 -> 匯出檔案 -> 產出 PDF

from System import DateTime
from System.IO import Directory, Path
from Spotfire.Dxp.Application.Export import PdfExportSettings
from Spotfire.Dxp.Application.Visuals import TablePlot

def ensure_dir(folder):
if not Directory.Exists(folder):
Directory.CreateDirectory(folder)

def find_visual(page, title_keyword):
for v in page.Visuals:
if v.Title and title_keyword.lower() in v.Title.lower():
return v
raise Exception("找不到 Visual:包含關鍵字 '{}'".format(title_keyword))

# 1) 建立輸出資料夾(示範用:D:\SpotfireExports\YYYY-MM-DD)
today = DateTime.Now.ToString("yyyy-MM-dd")
base_folder = r"D:\SpotfireExports"
export_folder = Path.Combine(base_folder, today)
ensure_dir(export_folder)

print("[INFO] Export folder = " + export_folder)

# 2) 找到目標頁面(示範:用名稱找,不用索引)
target_page = None
for p in Document.Pages:
if p.Title and "Yield" in p.Title:
target_page = p
break
if target_page is None:
raise Exception("找不到頁面:Title 包含 'Yield'")

# 3) 找到目標表格 Visual
table_visual = find_visual(target_page, "Summary")
table_plot = table_visual.As[TablePlot]()

# 4) 套用篩選條件(示範:固定條件字串)
table_plot.Data.WhereClauseExpression = "[Device] = 'DEMO_DEVICE'"
print("[INFO] Apply filter: [Device] = 'DEMO_DEVICE'")

# 5) 匯出 CSV(示範:ExportVisual 方式)
csv_path = Path.Combine(export_folder, "demo_summary.csv")
Document.ActivePageReference = target_page
table_visual.ExportText(csv_path)
print("[OK] CSV exported: " + csv_path)

# 6) 匯出 PDF(示範:以 Report 匯出)
pdf_path = Path.Combine(export_folder, "demo_report.pdf")
settings = PdfExportSettings()
Document.Pages[0].ExportToPdf(pdf_path, settings)
print("[OK] PDF exported: " + pdf_path)

這段示範做對了什麼?

  • 輸出路徑Path.Combine 組合,避免手刻反斜線錯誤

  • 找不到頁面/視覺化元件會 直接丟 Exception,Automation log 一看就懂

  • 每一步都有 [INFO] / [OK] log,排程出問題很好查


Automation 上線前必做檢查清單(照抄即可)

✅ 檔案與權限

  • Automation Services 的執行帳號是誰?(Windows service account)

  • 它是否對輸出資料夾有「建立資料夾 + 寫入檔案」權限?

  • 輸出磁碟是否存在?(不要假設一定有 C: 或 D:)

✅ Spotfire 文件穩定性

  • 不要依賴固定頁面索引(Page[3] 這種)

  • Visual Title 可能被改,建議用 contains/keyword 尋找或固定 ID

  • 找不到時要丟錯,不要默默跳過

✅ 資料來源與資料庫

  • Automation 使用的 Data Source 與 Analyst 是否一致?

  • Service account 是否有 DB 權限?

  • 刷新後資料是否為空?(要在 log 印出筆數或關鍵欄位)

✅ Log 可追蹤性

  • log 必須包含:輸出資料夾、匯出檔名、篩選條件、是否成功

  • 任何關鍵步驟失敗要中止(Exception)


常見 QA:我怎麼判斷它到底有沒有「真的匯出成功」?

你可以用最直覺的 3 個訊號:

  1. Automation Job log 是否看到「OK exported」之類的成功訊息

  2. 伺服器上該資料夾是否真的出現檔案

  3. 檔案大小是否合理(0 KB / 很小通常代表內容沒出來或資料為空)


結語:重點不是「同一台機器」,而是「同一個身分、同一套權限、同一條路徑可寫」

Spotfire Automation Services 成功與否,最常見的根因不是腳本語法,而是:

  • 執行帳號權限

  • 資料來源連線方式

  • 路徑寫入可用性

  • 腳本是否依賴 UI 變動因素

  • log 是否足夠讓你定位錯誤

只要把這些做扎實,你的 Spotfire 報表就能穩定做到:

  • 每週自動輸出 CSV

  • 每月自動產出 PDF

  • 並可被排程、可追蹤、可維護

留言

這個網誌中的熱門文章

🔍Vue.js 專案錯誤排查:解決 numericFields is not defined 與合併儲存格邏輯最佳化

🖥️遠端桌面連線完整新手指南:Windows RDP、Chrome Remote Desktop、AnyDesk、TeamViewer 一次搞懂

🔎EF Core 連 Oracle 出現 ORA-00600 [kpp_concatq:2] 的完整排錯指南(含 EF Core ToString/CultureInfo 錯誤)