NanoXLSX.Reader 3.2.1
Loading...
Searching...
No Matches
FinalizingProcessor.cs
1/*
2 * NanoXLSX is a small .NET library to generate and read XLSX (Microsoft Excel 2007 or newer) files in an easy and native way
3 * Copyright Raphael Stoeckli © 2026
4 * This library is licensed under the MIT License.
5 * You find a copy of the license in project folder or on: http://opensource.org/licenses/MIT
6 */
7
8using System;
9using System.Collections.Generic;
10using NanoXLSX.Interfaces;
11using NanoXLSX.Interfaces.Reader;
12using NanoXLSX.Registry;
13using NanoXLSX.Registry.Attributes;
14
16{
20 [NanoXlsxPlugIn(PlugInUUID = PlugInUUID.FinalizingProcessor)]
21 public class FinalizingProcessor : IPluginReadProcessor
22 {
26 public IOptions Options { get; set; }
27
31 public Action<Workbook, string, IOptions, int?> InlinePluginHandler { get; set; }
32
36 public Workbook Workbook { get; set; }
37
44 public void Init(Workbook workbook, IOptions readerOptions, Action<Workbook, string, IOptions, int?> inlinePluginHandler)
45 {
46 // stream can be ignore
47 Workbook = workbook;
48 InlinePluginHandler = inlinePluginHandler;
49 Options = readerOptions;
50 }
51
55 public void Execute()
56 {
57 FinalizeDefinedNames();
58
59 // TODO Add further regular finalizing tasks here
60
61 InlinePluginHandler?.Invoke(Workbook, PlugInUUID.FinalizingInlineProcessor, Options, null);
62 }
63
69 private void FinalizeDefinedNames()
70 {
71 List<WorksheetDefinition> worksheetDefinitions = Workbook.AuxiliaryData.GetDataList<WorksheetDefinition>(PlugInUUID.WorkbookReader, PlugInUUID.WorksheetDefinitionEntity);
72 if (Workbook.Worksheets.Count < worksheetDefinitions.Count)
73 {
74 return;
75 }
76 List<DefinedNameDefinition> definitions = Workbook.AuxiliaryData.GetDataList<DefinedNameDefinition>(PlugInUUID.WorkbookReader, PlugInUUID.DefinedNameEntity);
77 foreach (DefinedNameDefinition definition in definitions)
78 {
79 Worksheet localSheet = null;
80 if (definition.LocalSheetId.HasValue)
81 {
82 int i = definition.LocalSheetId.Value;
83 if (i >= 0 && i < Workbook.Worksheets.Count)
84 {
85 localSheet = Workbook.Worksheets[i];
86 }
87 }
88 DefinedName resolvedDefinedName = DefinedName.ResolveDefinedName(definition.Name, definition.Reference, Workbook, localSheet, definition.Comment);
89 Workbook.AddDefinedName(resolvedDefinedName);
90 }
91 RetagReferenceCells(); // TODO check & handle array cell references
92 }
93
99 private void RetagReferenceCells()
100 {
101 if (!Workbook.Features.ContainsDefinedNames)
102 {
103 return;
104 }
105 foreach (Worksheet ws in Workbook.Worksheets)
106 {
107 Dictionary<string, Tuple<Cell, DefinedName>> referenceCellCopies = new Dictionary<string, Tuple<Cell, DefinedName>>(StringComparer.Ordinal);
108 foreach (Cell cell in ws.Cells.Values)
109 {
110 if (cell.DataType == Cell.CellType.Formula && cell.Formula != null)
111 {
112 DefinedName definedName = Workbook.GetDefinedName(cell.Formula.Expression, ws)
113 ?? Workbook.GetDefinedName(cell.Formula.Expression);
114 if (definedName != null)
115 {
116 referenceCellCopies.Add(cell.CellAddress, new Tuple<Cell, DefinedName>(cell.Copy(), definedName));
117 }
118 }
119 }
120 if (referenceCellCopies.Count == 0)
121 {
122 continue;
123 }
124 HashSet<string> processedAddresses = new HashSet<string>(StringComparer.Ordinal);
125 foreach (KeyValuePair<string, Tuple<Cell, DefinedName>> cell in referenceCellCopies)
126 {
127 if (processedAddresses.Contains(cell.Key))
128 {
129 continue; // Skip processed cells
130 }
131 IReadOnlyList<Address> addresses;
132 object cachedValue = cell.Value.Item1.Formula.CachedValue;
133 if (cell.Value.Item1.CellStyle == null) // Re-add formula cells with full resolution
134 {
135 addresses = ws.AddCellReference(cell.Value.Item2, cell.Key, cachedValue);
136 }
137 else
138 {
139 addresses = ws.AddCellReference(cell.Value.Item2, cell.Key, cell.Value.Item1.CellStyle, cachedValue);
140 }
141 FormulaData restoredFormula = ws.Cells[cell.Key].Formula;
142 restoredFormula.CachedValue = cachedValue;
143 restoredFormula.CachedValueType = cell.Value.Item1.Formula.CachedValueType;
144 foreach (Address address in addresses)
145 {
146 processedAddresses.Add(address.ToString());
147 }
148 }
149 }
150 }
151
152 }
153}
Class representing a processor (no stream handling) for finalizing tasks after all parts are read fro...
void Execute()
Method to execute the main logic of the plug-in (interface implementation).
Workbook Workbook
Workbook reference where read data is stored (should not be null).
void Init(Workbook workbook, IOptions readerOptions, Action< Workbook, string, IOptions, int?> inlinePluginHandler)
Initialization method (interface implementation).
Action< Workbook, string, IOptions, int?> InlinePluginHandler
Reference to the ReaderPlugInHandler, to be used for post operations in the Execute method.