LotusScript 處理附件:EmbedObject、NotesEmbeddedObject 與 GetAttachment 捷徑

LotusScript 處理附件:EmbedObject、NotesEmbeddedObject 與 GetAttachment 捷徑

2026.07.07 約 852 字

一個 agent 要把產生好的 PDF 附到文件上再寄出;另一個要掃過進來的文件、把每個附件抽到網路資料夾、再刪掉原檔。兩者都是家常工作,也都經過同一個類別 —— NotesEmbeddedObject —— 加上 NotesRichTextItemNotesDocument 上的幾個方法。這組 API 帶著一些 OLE 時代的包袱,所以訣竅是知道哪些部分現在還重要。


重點摘要

  • 一個 NotesEmbeddedObject「代表以下之一:一個嵌入物件、一個物件連結、一個檔案附件」。對現代開發來說,檔案附件才是重要的那個 —— OLE 嵌入/連結是 Windows-only 的遺留功能。
  • 附加檔案Set eo = rtitem.EmbedObject(EMBED_ATTACHMENT, "", "c:\path\file.pdf")。型別常數是 EMBED_ATTACHMENT(1454)、EMBED_OBJECT(1453)、EMBED_OBJECTLINK(1452)。
  • 依名稱找單一附件doc.GetAttachment(fileName$) —— 它能找到附件,不管附件放在哪個 rich text item(或根本不在),這正是它的重點。
  • 抽取到磁碟Call eo.ExtractFile(path$) —— 只限附件;它對 OLE 物件/連結會出錯,所以永遠要用 eo.Type = EMBED_ATTACHMENT 把關。
  • 陷阱NotesDocument.EmbeddedObjects「不會回傳檔案附件」—— 改用 rtitem.EmbeddedObjects(逐 rich text item)或 GetAttachment
  • doc.HasEmbedded 是「這份文件有沒有帶任何附件/嵌入物」的快速 Boolean 檢查。

附加檔案

EmbedObject 住在 rich text item 上。對一個純檔案附件,型別是 EMBED_ATTACHMENT、class 字串留空、source 是檔案路徑:

Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim rtitem As NotesRichTextItem
Dim eo As NotesEmbeddedObject
Set db = session.CurrentDatabase
Set doc = New NotesDocument(db)
Set rtitem = New NotesRichTextItem(doc, "Body")
Set eo = rtitem.EmbedObject(EMBED_ATTACHMENT, "", "c:\reports\q1.pdf")
doc.Form = "Main Topic"
doc.Subject = "Here's the Q1 report, attached"
Call doc.Save(True, True)

這段是官方範例(把檔案路徑更新過)。可選的第四個 name$ 參數只對 OLE 物件有意義、不適用附件,所以這裡不給。文件有一個要求:資料庫要設好 default view,EmbedObject 才能運作。

找附件 —— 以及 EmbeddedObjects 陷阱

抵達附加檔案有三條路,而它們之間的差別正是值得記牢的部分:

  • doc.HasEmbedded —— 唯讀 Boolean,文件有任何嵌入、連結或附件時為 True。做更多事之前的便宜把關。
  • doc.GetAttachment(fileName$) —— 回傳某個具名附件的 NotesEmbeddedObject,或 Nothing。依文件,它的強項是能找到「不在任何 rich text item 裡的檔案附件……以及包含在 rich text item 裡的檔案附件」。所以你不需要知道檔案附在哪。(注意:回傳物件的 ParentNothing,因為你不是透過 rich text item 拿到它的。)
  • rtitem.EmbeddedObjects —— 那個 rich text item 裡嵌入物件的陣列,它確實包含檔案附件。

陷阱是大家最先伸手去拿的第四個選項:doc.EmbeddedObjects。class 頁明白寫著文件層級的版本**「不會回傳檔案附件」**—— 所以對 doc.EmbeddedObjects 跑迴圈,會悄悄跳過你通常正想要的那個東西。用 rich-text-item 陣列或 GetAttachment

抽取與移除

要把附件拉到磁碟,走過 rich text item 的物件、用附件型別把關、再呼叫 ExtractFile。這是官方寫法:

Dim doc As NotesDocument
Dim rtitem As Variant
Dim fileCount As Integer
Const MAX = 100000
fileCount = 0
'...set value of doc...
Set rtitem = doc.GetFirstItem("Body")
If (rtitem.Type = RICHTEXT) Then
Forall o In rtitem.EmbeddedObjects
If (o.Type = EMBED_ATTACHMENT) And (o.FileSize > MAX) Then
fileCount = fileCount + 1
Call o.ExtractFile("c:\reports\newfile" & Cstr(fileCount))
Call o.Remove
Call doc.Save(True, True)
End If
End Forall
End If

從這段官方片段帶兩件事進正式環境。第一,o.Type = EMBED_ATTACHMENT 這道把關不是可選的 —— ExtractFile 對 OLE 物件與物件連結會丟錯,所以沒檢查就抽取,一遇到帶有非附件嵌入物的文件就會炸。第二,注意抽出的檔名(newfile1newfile2…)沒有副檔名 —— 那是 HCL 範例的怪癖;正式程式要用原檔名或真正的副檔名抽取,檔案才打得開。

o.Remove 刪掉附件,而(跟所有 rich-text 編輯一樣)變更要到 doc.Save 才落盤。過程中好用的 NotesEmbeddedObject 屬性:NameFileSize(bytes,給附件用)、TypeClassVerbs(僅 OLE)、以及 Source

同類別在其他語言

LotusScriptJavaSSJS / XPages
NotesEmbeddedObjectEmbeddedObjectEmbeddedObject
NotesRichTextItem.EmbedObjectRichTextItem.embedObjectRichTextItem.embedObject

Java 與 SSJS 的介面與這個對應 —— rtitem.embedObject(...)doc.getAttachment(...)eo.extractFile(...)、同一個 EMBED_ATTACHMENT 常數、以及同樣「文件層級 getEmbeddedObjects() 略過附件」的行為。建議原樣沿用:透過 getAttachment 或 rich-text item 抵達附件,而不是文件層級的集合。

參考來源

← 回到文章列表