---
title: Create a print batch with documents
summary: Builds a new print-control batch header and its associated documents in memory, then persists the header followed by every document in one save.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Services.Printing.Remote
reference_type: package
operation_id: OP-003
trigger: Caller invokes clsXDocumentCollection.NewXDocumentCollection to start a batch, adds one or more documents, and calls Save()
---

# Create a print batch with documents

This operation is the primary way a batch of documents is queued for printing. A caller starts a new `clsXDocumentCollection`, which builds an in-memory print-control header, adds one or more documents to the collection, and calls `Save()`. Saving persists the header first, then every document, so a batch and its documents are always created together in this workflow.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-003 |
| **Trigger** | Caller invokes `clsXDocumentCollection.NewXDocumentCollection(...)`, calls `AddXDocument()` for each document, and calls `Save()` |
| **Inputs** | `XPrintControlSeqNum`, directory name, XML file name, duplex mode, optional MD5 hash (for the header); per document: file name, document type code, email address, fax number, indexed contents text, ten sort values, start value, print group text |
| **Outputs** | Inserted row in `XPRINT_CONTROL`; one inserted row per document in `XDOCUMENT`; error messages on row-count contention for either |
| **Primary components** | `clsXDocumentCollection.Create`, `clsXDocumentCollection.AddXDocument`, `clsXDocumentCollection.Save`, `clsXDocument.Create`, `clsXDocument.BeforeInsert`/`AfterInsert` |
| **Entry point** | `Services\SAIF.Services.Printing.Remote\clsXDocumentCollection.vb`, `Services\SAIF.Services.Printing.Remote\clsXDocument.vb` |

## Steps

1. **Start a new batch.** Caller invokes `clsXDocumentCollection.NewXDocumentCollection(inDataportal, inXPrintControlSeqNum, inDirectoryName, inXMLFileName, inDuplexMode, inMD5HashValue)`, which calls `Create()`.
2. **Build the in-memory header.** `Create()` sets `XPrintControlSeqNum` from the criteria, then constructs the header via `clsXPrintControl.NewXPrintControl(MyCriteria.DataPortalInfo, XPrintControlSeqNum)` and populates its directory name, duplex mode, XML file name, and MD5 hash from the criteria. The header is held in memory only at this point — it is not yet saved.
   - This header construction and its later persistence follow the same Create/Insert behavior described in [Print-control batch header lifecycle](print-control-batch-header-lifecycle.md); this operation does not duplicate that header logic, it invokes it as part of `Save()` (step 5).
3. **Add documents to the batch.** Caller calls `AddXDocument()` one or more times. Each call invokes `clsXDocument.NewXDocument(MyCriteria.DataPortalInfo, XPrintControlSeqNum, PrintGroupText)`, which calls `clsXDocument.Create()`:
   - If the document's criteria `XDocumentSeqNum` is `0`: `Create()` calls `MyCriteria.DataPortalInfo.GetNextSeqNum("XDOCUMENT_SEQ")` to generate the primary key.
   - `Create()` sets `PrintGroupText` and `XPrintControlSeqNum` from the criteria, then defaults `CopiesCount = 1` and `XBinTypeCode = "AUTO"` ([BR-005](../business-rules.md#br-005-default-bin-type-on-document-creation)).
   - `AddXDocument()` also applies the batch's `DuplexMode` to the new document before adding it to the collection.
4. **Increment the print-group counter (optional).** Caller may invoke `IncrementPrintGroupNumber()` between `AddXDocument()` calls to advance the batch's print-group sequence number, which feeds the `PrintGroupText` computed property (prefix + timestamp + group number) used by subsequent documents.
5. **Save the batch.** Caller calls `Save()`, which first calls `ApplyEdit()`, then `XPrintControl.Save()` to persist the header.
   - If the header save succeeds: `MyBase.Save()` runs, persisting each added document in turn via its own `BeforeInsert`/`AfterInsert` lifecycle, executing [SQL-006](../sql/SQL-006-saif-services-printing-remote.md) (`INSERT INTO XDOCUMENT ...`, [XDOCUMENT](../database-tables.md#xdocument)) for each document with its 22 bound parameters (copies, document type code, email address, fax number, file name, indexed contents text, ten sort values, start value, bin type code, document sequence number, print-control sequence number, print group text, duplex code).
     - Each document's `AfterInsert` checks `RowsAffected <> 1` and adds `InsertError` on contention ([BR-001](../business-rules.md#br-001-row-count-contention-check)).
   - If the header save fails (`XPrintControl.Save()` returns `False`): the collection's own `Save()` does not explicitly return a value for this branch, so the outcome for the caller in this path is not confirmed from source.**

## Process flow

The following diagram visualizes building and saving a print batch with its documents.

```mermaid
flowchart TD
	Start([Caller starts NewXDocumentCollection]) --> Hdr[Create: build in-memory<br>XPrintControl header]
	Hdr --> AddLoop[Caller calls AddXDocument<br>for each document]
	AddLoop --> DocCreate[Document Create:<br>generate seq num,<br>default CopiesCount=1,<br>XBinTypeCode=AUTO]
	DocCreate --> More{More documents?}
	More -->|Yes| AddLoop
	More -->|No| Save[Caller calls Save]
	Save --> HdrSave[XPrintControl.Save<br>Insert into XPRINT_CONTROL]
	HdrSave --> HdrCheck{Header save succeeded?}
	HdrCheck -->|No| Unclear([Outcome not confirmed<br>from source])
	HdrCheck -->|Yes| DocSave[Base Save: Insert each<br>document into XDOCUMENT]
	DocSave --> DocCheck{RowsAffected = 1<br>per document?}
	DocCheck -->|No| DocErr([InsertError added<br>per failing document])
	DocCheck -->|Yes| Done([Batch and documents persisted])
```

## Failure and edge-case behavior

- The header is saved before any document; if the header insert fails contention-wise, `AfterInsert` on the header adds an error, but whether that error alone prevents document persistence (short-circuits `Save()`) is not fully confirmed — `XPrintControl.Save()`'s boolean return is checked, but its exact failure semantics under contention (versus a hard exception) are not verifiable purely from this library's source.**
- Newly added documents always receive `CopiesCount = 1` and `XBinTypeCode = "AUTO"` regardless of caller intent unless the caller explicitly overrides these properties after `AddXDocument()` returns ([BR-005](../business-rules.md#br-005-default-bin-type-on-document-creation)).
- `PrintGroupText` is computed from a prefix, a timestamp captured at collection construction, and a group number that only advances when the caller explicitly calls `IncrementPrintGroupNumber()` — documents added without an intervening call share the same print group text.
- `clsXDocument` has no live update or delete lifecycle — once a document is inserted via this operation, no method in this library modifies or removes it individually; documents are only removed in bulk via [Delete documents for a batch](delete-documents-for-a-batch.md).

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with `**` could not be confirmed; treat as unknown until verified.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

## Sources
- `Services\SAIF.Services.Printing.Remote\clsXDocumentCollection.vb`
- `Services\SAIF.Services.Printing.Remote\clsXDocument.vb`
- `Services\SAIF.Services.Printing.Remote\clsXPrintControl.vb`
