Files
2026-04-17 14:55:32 -04:00

10 KiB
Raw Permalink Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
Common/DTS.Common.Serialization/XLSX/Excel.File.cs
Common/DTS.Common.Serialization/XLSX/Excel.File.Writer.cs
2026-04-16T03:37:36.193666+00:00 Qwen/Qwen3-Coder-Next-FP8 1 3504eb010d91451f

XLSX

Documentation: DTS.Serialization.XLSX.File


1. Purpose

This module provides XLSX-specific serialization functionality for Test objects, implementing the abstract Serialization.File base class and the IWritable<Test> interface. Its primary purpose is to export test data (e.g., analog channel measurements) into Excel-compatible .xlsx files using the Open XML SDK. Currently, it supports exporting Engineering Units (EU) by default, with optional controls for exporting raw ADC counts (ExportADC) and millivolt values (ExportMV). The implementation is tightly coupled to the Test model and its channel hierarchy, and it supports both raw and filtered data export based on runtime configuration.


2. Public Interface

public partial class File : Serialization.File, IWritable<Test>

  • public File()
    Constructor. Initializes the base class with "XLSX" as the file type identifier.

  • public IWriter<Test> Exporter { get; }
    Returns the singleton Writer instance for this File. Lazily instantiates a Writer on first access using DefaultEncoding. Throws an Exception (wrapping the inner exception) if instantiation fails.

  • public bool ExportADC { set; }
    Sets the ExportADC property on the underlying Writer instance. Controls whether raw ADC values are exported.

  • public bool ExportEU { set; }
    Sets the ExportEU property on the underlying Writer. Controls whether Engineering Units (EU) are exported (default: true).

  • public bool ExportMV { set; }
    Sets the ExportMv property on the underlying Writer. Controls whether millivolt (mV) values are exported.

Note

: All three export flags (ExportADC, ExportEU, ExportMV) are setters only on File. There is no public getter, and the flags are applied only during the Write(...) call on the Writer.


public class Writer : Writer<File>, IWriter<Test>

  • internal File WriterParent { get; }
    Reference to the owning File instance.

  • public bool ExportADC { get; set; }
    Gets/sets whether to export raw ADC values.

  • public bool ExportEU { get; set; }
    Gets/sets whether to export Engineering Units.

  • public bool ExportMv { get; set; }
    Gets/sets whether to export millivolt values.

  • public double Start { get; set; }
    Start time (in seconds) for data slicing.

  • public double Stop { get; set; }
    Stop time (in seconds) for data slicing.

  • public bool Filtered { get; set; }
    If true, applies software filtering (via SaeJ211Filter) to EU data before export.

  • public void Write(string pathname, string id, Test test, bool bFiltering, bool includeGroupNameInISOExport, double minStartTime, int dataCollectionLength)
    Overload 1 (incomplete implementation) — currently has no body.

  • public void Write(string pathname, string id, string dataFolder, Test test, bool bFiltering, bool includeGroupNameInISOExport, FilteredData fd, Test.Module.Channel tmChannel, int channelNumber, BeginEventHandler beginEventHandler, CancelEventHandler cancelEventHandler, EndEventHandler endEventHandler, TickEventHandler tickEventHandler, ErrorEventHandler errorEventHandler, CancelRequested cancelRequested, double minStartTime, int dataCollectionLength)
    Overload 2 (full implementation) — writes the Test object to an .xlsx file at pathname.

    • Uses a template file (XLSXExportTemplate.xlsx) located in ReportTemplates.
    • Writes metadata (inception date/time, test ID, description) to fixed cells in the "Data" worksheet.
    • Writes per-channel metadata (sample rate, filter cutoff, units, etc.) to rows 623.
    • Writes time-series data starting at row 24.
    • Applies filtering only if Filtered is true and bFiltering is true.
    • Uses SAX-style streaming (OpenXmlReader/OpenXmlWriter) for efficient large-data export.
    • Fires progress (tickEventHandler), error (errorEventHandler), and completion (endEventHandler) callbacks.
    • Clears RowIndexToRow and _stringLookup caches before each write.
    • Forces full recalculation on load (ForceFullCalculation = true, FullCalculationOnLoad = true).
    • Adds a date/time number format style (NumberFormatId = 14) to the stylesheet.
    • Releases channel data (UnSet()) and triggers full garbage collection after writing.
  • public void Initialize(...)
    Overload — currently has no body.

  • private static Common.DAS.Concepts.DataScaler GetDataScaler(Test.Module.AnalogInputChannel)
    Constructs and configures a DataScaler instance from an AnalogInputChannel, including linearization, scaling, zeroing, and excitation parameters.

  • protected Cell GetCell(Worksheet worksheet, string xColumn, UInt32 rowIndex, bool bLookForCell = true)
    Retrieves or inserts a cell at the given column and row. Uses RowIndexToRow cache for performance.

  • private static Cell InsertCellInWorksheet(...)
    Inserts a cell into the worksheet, maintaining Open XML cell ordering requirements.

  • private void WriteTime(...) / WriteDate(...) / WriteDouble(...) / WriteString(...)
    Helper methods to write typed values into cells, using shared strings for text and appropriate cell types/styles.

  • private static string GetColumn(int index)
    Converts a zero-based column index to Excel column letters (e.g., 0 → "B", 1 → "C"). Note: Starts at column B (index 0), not A.

  • private int InsertSharedStringItem(string text, SharedStringTablePart)
    Inserts or retrieves a shared string index. Uses _stringLookup dictionary for O(1) lookup.

  • private void AddStyleSheet(SpreadsheetDocument)
    Adds a date/time number format (NumberFormatId = 14) to the stylesheet and caches its index.

  • internal Writer(File fileType, int encoding)
    Constructor. Sets default export flags: ExportADC = false, ExportEU = true, ExportMv = false.


3. Invariants

  • Cell ordering: Cells in a row must be in ascending CellReference order (enforced by InsertCellInWorksheet).
  • Shared string uniqueness: _stringLookup ensures each unique string is stored only once in the shared string table.
  • Data row indexing: Time-series data rows start at row 24 (24 + sampleIndex).
  • Channel column indexing: Columns are assigned sequentially starting at column B (GetColumn(i) where i = 0"B").
  • Metadata row layout (fixed per channel):
    • Row 6: Sample rate (Hz)
    • Row 7: AA filter rate (Hz)
    • Row 8: Channel index (1-based)
    • Row 9: ISO code
    • Row 10: Channel name (ChannelName2)
    • Row 12: Serial number
    • Row 13: Filter cutoff (Hz) — 0 if not filtered
    • Row 14: Filter name — only if filtered
    • Row 15: Engineering units
    • Row 17: Pre-trigger samples
    • Row 18: Post-trigger samples
    • Row 19: DataZeroLevelAdc
    • Row 20: ADC-to-EU scaling factor
    • Row 21: ADC-to-mV scaling factor
    • Row 23: Channel label ("Chan {i}: {name}")
  • Time calculation: Time value for sample n is computed as:
    time = (StartRecordSampleNumber - TriggerSampleNumber[0] + n) / SampleRateHz
    
    where n is adjusted for minStartTime and per-channel start offsets.

4. Dependencies

External Dependencies

  • DocumentFormat.OpenXml — Core Open XML SDK for reading/writing .xlsx files.
  • DTS.Common.Utilities.Logging — Uses APILogger.Log(...) for non-fatal exceptions (e.g., WindowAverageADC failures).
  • DTS.Slice.Control — Imports FilteredData, FilteredChannelData, and related filtering types.

Internal Dependencies

  • DTS.Serialization — Inherits from Serialization.File.
  • DTS.Common.DAS.Concepts — Uses DataScaler and related types.
  • DTS.Slice.Control — Uses SaeJ211Filter, FilteredData, and CancelRequested.
  • Test model — Expects Test.Module.AnalogInputChannel, Test.Module.Channel, and PersistentChannelInfo with Data array.

Dependencies on this Module

  • Any code requiring XLSX export of Test objects (e.g., UI export buttons, batch processing pipelines) will instantiate DTS.Serialization.XLSX.File and call Exporter.Write(...).

5. Gotchas

  • Column offset: GetColumn starts at column B (index 0 → "B"), not A. This is hardcoded and not configurable.
  • String caching: _stringLookup is reset per Write call (cleared in Write), but reused within a single write for efficiency. Not thread-safe.
  • Row caching: RowIndexToRow is a static dictionary. It is cleared at the start of each Write, but if multiple threads call Write concurrently, race conditions may occur.
  • Filtered data is precomputed: When Filtered = true, all EU data is pre-filtered into a double[][] before streaming. This may consume significant memory for large datasets.
  • Template dependency: Requires XLSXExportTemplate.xlsx in the ReportTemplates subdirectory of the application base directory. Missing file → copy failure.
  • GC pressure mitigation: Explicit GC.Collect() and heap compaction are triggered after writing. This may cause latency spikes.
  • No export flag enforcement in data loop: The Write method only exports EU data (via ds.GetEU(...)), regardless of ExportADC, ExportEU, or ExportMV settings. These flags are set on the Writer, but the current implementation ignores them in the data loop.
  • FilteredChannelData is commented out: The property FilteredChannelData is commented out in Excel.File.Writer.cs, suggesting incomplete or deprecated functionality.
  • UseLegacyTDCSoftwareFiltering is used but not defined: In the filtering loop, UseLegacyTDCSoftwareFiltering is referenced but not declared in the visible scope — likely a field or property defined elsewhere in the Writer class (not shown).
  • minStartTime is used but not validated: Assumes minStartTime ≤ actual start time of data; no bounds checking is evident.
  • filteredData is set to null after use: A manual nulling of filteredData is done, but this may be redundant with the end of scope — possibly legacy cleanup.

Documentation generated from source files Excel.File.cs and Excel.File.Writer.cs.