NotesNoteCollection: the Swiss-army tool for NSF design elements
What NotesNoteCollection is
NotesNoteCollection is the LotusScript class for batch-operating on “notes”.
A “note” is the NSF’s internal storage unit — anything that gets a Note ID: data documents, forms, views, folders, agents, ACLs, profile documents, style sheets. Every one of those is a note.
So this class covers a wide surface, controlled by per-class flags:
- Data: data documents
- Design elements: forms, views, folders, pages, subforms, shared fields
- Code: agents, script libraries, Java resources, action bars, the database script
- Resources: image resources, style sheets
- Security / config: ACL, profile documents, replication formulas
- Misc: design indices, format elements, code elements
Its sweet spot:
“I need to batch-process some class of note in the NSF — audit every agent, DXL-export the entire design for version control, harvest every note modified in the last week.”
If you already know NotesDocumentCollection: these are different tools. NotesDocumentCollection only deals with data documents; NotesNoteCollection handles everything at the note level. There’s a full side-by-side comparison after the worked examples below.
Construction: CreateNoteCollection(Boolean)
Obtained from NotesDatabase:
Set nc = db.CreateNoteCollection(False)That boolean controls the initial state of every Select* property:
True→ everySelect*starts asTrue(start with everything, then turn off what you don’t want)False→ everySelect*starts asFalse(start with nothing, then turn on what you want)
False is more common in practice — you usually know which class of element you need, so you start empty and switch on the relevant flags.
32 properties — pick what you want
The full list documented in the source:
Lifecycle / general
| Property | Purpose |
|---|---|
Count | Number of notes the collection covers |
Parent | The owning NotesDatabase |
LastBuildTime | When BuildCollection last completed |
SinceTime | Restrict to notes modified after this timestamp |
SelectionFormula | Extra @Formula filter on top of the Select* flags |
27 Select* flags (one per note class)
| Bucket | Properties |
|---|---|
| Data / flow | SelectDocuments, SelectFolders, SelectViews |
| Form family | SelectForms, SelectSubforms, SelectSharedFields, SelectFrameSets, SelectPages |
| Code | SelectAgents, SelectScriptLibraries, SelectActions, SelectDatabaseScript |
| Resources | SelectImageResources, SelectJavaResources, SelectStyleSheetResources, SelectIcon |
| Outline / nav | SelectOutlines, SelectNavigators |
| Security / config | SelectACL, SelectProfiles, SelectReplicationFormulas, SelectDataConnections |
| Help | SelectHelpAbout, SelectHelpUsing, SelectHelpIndex |
| Misc | SelectMiscCodeElements, SelectMiscFormatElements, SelectMiscIndexElements |
Each is a Boolean. To grab every agent and every view:
Set nc = db.CreateNoteCollection(False)nc.SelectAgents = Truenc.SelectViews = TrueCall nc.BuildCollection()14 methods — three groups
Lifecycle
| Method | Purpose |
|---|---|
BuildCollection | Walk the database with the Select* flags + SelectionFormula and harvest the matching notes. Mandatory — without it Count = 0 |
ClearCollection | Empty the collection (without resetting the Select* flags) |
Set operations
| Method | Purpose |
|---|---|
Add(noteOrCollection) | Add a single note or another collection |
Remove(noteOrCollection) | Remove from the collection |
Intersect(otherCollection) | Keep only notes that are in both |
Bulk presets
| Method | Purpose |
|---|---|
SelectAllNotes(Boolean) | Set all 27 Select* flags to True or False at once |
SelectAllDataNotes(Boolean) | Set just the data-related flags (SelectDocuments, etc.) |
SelectAllDesignElements(Boolean) | Set just the design-element flags |
SelectAllAdminNotes(Boolean) | Set just the admin flags (ACL, profiles, etc.) |
SelectAllCodeElements(Boolean) | Set just the code flags |
SelectAllFormatElements(Boolean) | Set just the format flags |
SelectAllIndexElements(Boolean) | Set just the index flags |
Iteration
| Method | Purpose |
|---|---|
GetFirstNoteID | Returns the first Note ID (string form, e.g. "NT00001ABC") |
GetNextNoteID(currentID) | Returns the next Note ID |
The documentation does not define GetLastNoteID, GetPrevNoteID, Merge, Subtract, or GetUNID — verify against the official docs when writing code.
Worked example 1: audit every agent in a database
Sub AuditAgents(db As NotesDatabase) Dim nc As NotesNoteCollection Dim noteID As String Dim doc As NotesDocument
Set nc = db.CreateNoteCollection(False) nc.SelectAgents = True Call nc.BuildCollection()
Print "Found " & nc.Count & " agent(s)"
noteID = nc.GetFirstNoteID() Do Until noteID = "" Set doc = db.GetDocumentByID(noteID) Print doc.GetItemValue("$TITLE")(0) & _ " | LastModified: " & doc.LastModified noteID = nc.GetNextNoteID(noteID) LoopEnd SubFour things this snippet gets right:
CreateNoteCollection(False)— start empty, turn on only what you neednc.SelectAgents = True— agents onlyBuildCollection()— mandatory; the collection is empty without itGetFirstNoteID/GetNextNoteIDreturn Note ID strings, notNotesDocumentobjects — you fetch the document yourself withdb.GetDocumentByID()
Worked example 2: list every view name (two ways compared)
A common real-world need: “get me a list of every view name in this database”. NotesNoteCollection can do it, but there’s a much shorter path:
' Method A: NotesNoteCollectionSet nc = db.CreateNoteCollection(False)nc.SelectViews = TrueCall nc.BuildCollection()
noteID = nc.GetFirstNoteID()Do Until noteID = "" Set doc = db.GetDocumentByID(noteID) Print doc.GetItemValue("$TITLE")(0) ' $TITLE is "Name|Alias|Alias" noteID = nc.GetNextNoteID(noteID)Loop' Method B: db.ViewsForAll v In db.Views Print v.Name ' v.Name is the resolved primary name ' v.Aliases is the alias arrayEnd ForAllTrade-offs:
Method A (NotesNoteCollection) | Method B (db.Views) | |
|---|---|---|
| Just want view names | Overkill | ✅ The standard idiom |
| Pick up views + folders + agents in one pass | ✅ Add SelectFolders=True, SelectAgents=True | ❌ Three separate calls (db.Views / db.Folders / db.Agents) |
Filter with SelectionFormula or SinceTime (e.g. “views modified in the last 7 days”) | ✅ Built in | ❌ Pull all, filter yourself |
Feed NotesDXLExporter | ✅ Direct input | ❌ Build the collection yourself |
| What you actually get back | Note ID strings (call GetDocumentByID separately) | NotesView objects ready to use (view.AllEntries, etc.) |
Picking the right one:
- “Just give me the view names” →
db.Views. Three lines, done. - “Mixed types, time/condition filtering, or DXL export pipeline” →
NotesNoteCollection.
One subtle point: db.Views includes folders (a folder is a specialised view). To strictly exclude folders, filter with view.IsFolder, or use Method A with SelectViews=True only — folders have their own SelectFolders flag.
Worked example 3: pulling data documents (you can, but you usually shouldn’t)
NotesNoteCollection can harvest data documents — just turn on SelectDocuments:
Set nc = db.CreateNoteCollection(False)nc.SelectDocuments = True ' data documents onlyCall nc.BuildCollection()
noteID = nc.GetFirstNoteID()Do Until noteID = "" Set doc = db.GetDocumentByID(noteID) Print doc.UniversalID & " | Form=" & doc.Form(0) noteID = nc.GetNextNoteID(noteID)LoopOr use the bulk preset nc.SelectAllDataNotes(True) to flip every data-related flag at once.
But — this isn’t usually how you reach for data. Each standard idiom has a shorter path:
| Need | Standard idiom | Why it beats NotesNoteCollection |
|---|---|---|
| All data documents | db.AllDocuments | One line; returns NotesDocumentCollection directly, no GetDocumentByID round-trip |
| Conditional query | DQL (NotesDominoQuery), then NQRP for post-processing | SQL-like syntax; the engine uses indexes automatically |
| Formula selection | db.Search(formula, ...) | Native @Formula input |
| Walking a view’s entries | NotesViewNavigator or view.AllEntries | Gives you the view’s own column metadata |
Where NotesNoteCollection actually beats them for data
There are three situations where it wins:
- Mixed harvest: data + design in one pass — e.g. “every note modified in the last 7 days, including views and agents” for an audit or backup
Call nc.SelectAllNotes(True)nc.SinceTime = New NotesDateTime(Now - 7)Call nc.BuildCollection()
- Feeding
NotesDXLExporter— when you want data plus design exported together for version control - Note IDs instead of
NotesDocumentobjects — writing tooling or audit logs that just need the IDs
One subtlety
SelectDocuments = True does not include:
- Deletion stubs
- Conflict documents are handled slightly differently from
NotesDocumentCollection
If you’re doing a “complete database audit” you’ll need to handle those edge cases separately.
The most common real use: DXL export
In practice, the dominant use case for NotesNoteCollection is feeding NotesDXLExporter:
Sub ExportAllDesignToDXL(db As NotesDatabase, outputPath As String) Dim nc As NotesNoteCollection Dim exporter As NotesDXLExporter Dim s As New NotesSession Dim stream As NotesStream
' 1. Collect every design element (no data documents) Set nc = db.CreateNoteCollection(False) Call nc.SelectAllDesignElements(True) Call nc.BuildCollection()
' 2. Open the output file Set stream = s.CreateStream() Call stream.Open(outputPath, "UTF-8")
' 3. Run the DXL exporter on the entire collection Set exporter = s.CreateDXLExporter() Call exporter.SetInput(nc) Call exporter.SetOutput(stream) Call exporter.Process()
Call stream.Close() Print "Export complete: " & outputPathEnd SubThis is the “templating tool” pattern — exporting an entire template database’s design as XML for version control, cross-environment deployment, or backup. NotesNoteCollection + NotesDXLExporter is the canonical path.
Advanced: full side-by-side with NotesDocumentCollection
If you already know NotesDocumentCollection, this table maps the differences at a glance:
NotesDocumentCollection | NotesNoteCollection | |
|---|---|---|
| Scope | Data documents only | Every note (design + data) |
| Element type | Always NotesDocument | Note ID strings (look the document up yourself) |
| Construction | db.AllDocuments, view.AllEntries.GetAllDocuments, etc. | Only db.CreateNoteCollection(Boolean) |
| Filtering | Done at the source (view, folder, query) | Select* flags + SelectionFormula |
| Set operations | Add doesn’t surface the original doc you added | Add / Remove / Intersect are first-class |
| Best for | Walking data, searching, batch updates | Design audits, DXL export, deployment tooling |
When not to use NotesNoteCollection
- Plain batch ops on data documents →
NotesDocumentCollectionor DQL (NotesDominoQuery) - Walking a view with entry-level metadata →
NotesViewNavigator - Just need a list of design elements →
NotesDatabase.GetView()/GetForm()/GetAgent()are simpler
The sweet spot is “I need to batch-process notes at the design level”. For that scenario, there’s no better tool.