Report save to disk¶
Renders a report (reusing a cached render where possible) and writes the resulting bytes to a caller-specified destination file, refusing to replace an existing file unless the caller explicitly requests an overwrite.
| Field | Value |
|---|---|
| Operation ID | OP-09 |
| Trigger | Save invoked |
| Inputs | overwrite As Boolean = False, DestinationFileName (instance property) |
| Outputs | Boolean — whether the destination file exists after the call |
| Primary components | ReportBase.Save, Render, IO.FileStream |
| Entry point | Public Function Save(Optional overwrite As Boolean = False) As Boolean |
Steps¶
- Checks whether
DestinationFileNamealready exists on disk (IO.File.Exists). - Proceeds only if the file does not already exist, or
overwriteisTrue— an existing destination file is not replaced unless the caller requests an overwrite (BR-PRT-014). - If neither condition holds: execution skips straight to step 5's existence check without touching the file.
- Requires
m_DestinationFileName.Length > 0before actually writing — saving requires a destination file name (BR-PRT-014). - If empty: no render and no write occurs, but execution still falls through to step 5.
- Calls
Render(overwrite)to ensurem_reportFileis populated (respectingRender's own render-result caching), then opensDestinationFileNamewithFileMode.Create(which itself truncates/overwrites at the OS level) and writes all ofm_reportFile's bytes.
Origin: This step is the full Report render lifecycle operation, including its render-result caching (BR-PRT-007). 5. Returns
IO.File.Exists(DestinationFileName)— re-checked fresh, not a cached flag carried over from step 1 — as the final result.
Process flow¶
flowchart TD
Start([Save called]) --> Check["Check file exists"]
Check --> Guard{"exists AND<br>not overwrite?"}
Guard -->|Yes| SkipWrite["skip write"]
Guard -->|No| Named{"DestinationFileName<br>set?"}
Named -->|No| SkipWrite
Named -->|Yes| Render["Render()<br>(→OP-06)"]
Render --> Write["FileStream.Create,<br>write bytes"]
Write --> Result(["Return File.Exists<br>(re-checked)"])
SkipWrite --> Result
Failure and edge-case behavior¶
- There is no try/catch around the
FileStreamwrite: anIOException(locked file, invalid path, disk full) propagates unhandled — a contrast withRender's andDistribute's caught-and-recorded failure pattern. - If
Renderinside step 4 fails silently (BR-PRT-010 — returnsFalsewith anErrorDetailbut no exception) and leavesm_reportFileasNothing, the subsequentfs.Write(m_reportFile, 0, m_reportFile.Length)would throw aNullReferenceException— a real, uncaught crash path.* - The final
IO.File.Existscheck meansSavecan returnTrueeven when nothing was written during this call, simply because a pre-existing file (from a prior run) is present and no overwrite was requested. This is the intended BR-PRT-014 semantics, not a bug.
Related documentation¶
- Index
- Overview
- Architecture
- Dependencies
- Operations and processes
- Business rules
- Configuration
- API reference
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.
Sources¶
SAIF.Services.Printing/Reporting/ReportBase.vbSAIF.Services.Printing/Reporting/IReport.vb