From 31a9cbfc2b9438af05b86e3469c9135332333cff Mon Sep 17 00:00:00 2001 From: omaus Date: Tue, 21 Mar 2023 22:22:47 +0100 Subject: [PATCH] Add static methods, update existing methods --- src/FsSpreadsheet/Tables/FsTable.fs | 111 ++++++++++++++++++---------- 1 file changed, 71 insertions(+), 40 deletions(-) diff --git a/src/FsSpreadsheet/Tables/FsTable.fs b/src/FsSpreadsheet/Tables/FsTable.fs index ee04f458..872be013 100644 --- a/src/FsSpreadsheet/Tables/FsTable.fs +++ b/src/FsSpreadsheet/Tables/FsTable.fs @@ -25,21 +25,21 @@ type FsTable (name : string, rangeAddress, showTotalsRow, showHeaderRow) = /// Returns all fieldnames as `fieldname*FsTableField` dictionary. member self.FieldNames - with get(cells) = + with get(cellsCollection) = if (_fieldNames <> null && _lastRangeAddress <> null && _lastRangeAddress.Equals(self.RangeAddress)) then _fieldNames; else _lastRangeAddress <- self.RangeAddress - //self.RescanFieldNames(cells) + //self.RescanFieldNames(cellsCollection) _fieldNames; - /// The FsTableFields of this FsTable. + /// The FsTableFields of this FsTable. member self.Fields - with get(cells) = + with get(cellsCollection) = let columnCount = base.ColumnCount() - Seq.init columnCount (fun i -> self.Field(i, cells)) + Seq.init columnCount (fun i -> self.GetField(i, cellsCollection)) /// Gets or sets if the header row is shown. member self.ShowHeaderRow @@ -64,7 +64,7 @@ type FsTable (name : string, rangeAddress, showTotalsRow, showHeaderRow) = /// Takes the respective FsCellsCollection for this FsTable and creates a new _fieldNames dictionary if the current one does not match. // TO DO: maybe HLW can specify above description a bit... - member private self.RescanFieldNames(cells : FsCellsCollection) = + member private self.RescanFieldNames(cellsCollection : FsCellsCollection) = printfn "Start RescanFieldNames" _fieldNames |> Seq.iter (fun kv -> printfn "Key: %s, index: %i, name: %s" kv.Key kv.Value.Index kv.Value.Name) @@ -73,7 +73,7 @@ type FsTable (name : string, rangeAddress, showTotalsRow, showHeaderRow) = _fieldNames <- new Dictionary() let headersRow = self.HeadersRow(false); let mutable cellPos = 0 - for cell in headersRow.Cells(cells) do + for cell in headersRow.Cells(cellsCollection) do let mutable name = cell.Value //GetString(); match Dictionary.tryGet name oldFieldNames with | Some tableField -> @@ -109,14 +109,30 @@ type FsTable (name : string, rangeAddress, showTotalsRow, showHeaderRow) = _fieldNames |> Seq.iter (fun kv -> printfn "Key: %s, index: %i, name: %s" kv.Key kv.Value.Index kv.Value.Name) - - member self.RescanRange () = + /// + /// Updates the FsRangeAddress of the FsTable according to the FsTableFields associated. + /// + member self.RescanRange() = let rangeAddress = _fieldNames.Values |> Seq.map (fun v -> v.Column.RangeAddress) |> Seq.reduce (fun r1 r2 -> r1.Union(r2)) base.RangeAddress <- rangeAddress + /// + /// Updates the FsRangeAddress of a given FsTable according to the FsTableFields associated. + /// + static member rescanRange (table : FsTable) = + table.RescanRange() + + /// + /// Returns a unique name consisting of the original name and an initial offset that is raised + /// if the original name with that offset is already present. + /// + /// + /// If true, the initial offset is always + /// + // TO DO: HLW: make this description more precise. What is this method even about? member this.GetUniqueName(originalName : string, initialOffset : int32, enforceOffset : bool) = let mutable name = originalName + if enforceOffset then string initialOffset else "" if _uniqueNames.Contains(name) then @@ -128,8 +144,12 @@ type FsTable (name : string, rangeAddress, showTotalsRow, showHeaderRow) = i <- i + 1 name <- originalName + string i + _uniqueNames.Add name |> ignore name + static member getUniqueNames originalName initialOffset enforceOffset (table : FsTable) = + table.GetUniqueName(originalName, initialOffset, enforceOffset) + //member this.AddFields(fieldNames : IEnumerable) = // _fieldNames = new Dictionary(); @@ -140,55 +160,66 @@ type FsTable (name : string, rangeAddress, showTotalsRow, showHeaderRow) = // _fieldNames.Add(name, new XLTableField(this, name) { Index = cellPos++ }); // } + /// Returns the FsTableField with given name. If an FsTableField does not exist under this name in the FsTable, adds it. + member self.Field(name : string, cellsCollection : FsCellsCollection) = + match Dictionary.tryGet name _fieldNames with + | Some field -> + field + | None -> + let maxIndex = + _fieldNames.Values + |> Seq.map (fun v -> v.Index) + |> fun s -> + if Seq.length s = 0 then 0 else Seq.max s + let range = + let offset = _fieldNames.Count + let firstAddress = FsAddress(self.RangeAddress.FirstAddress.RowNumber,self.RangeAddress.FirstAddress.ColumnNumber + offset) + let lastAddress = FsAddress(self.RangeAddress.LastAddress.RowNumber,self.RangeAddress.FirstAddress.ColumnNumber + offset) + FsRangeAddress(firstAddress,lastAddress) + let column = FsRangeColumn(range) + let newField = FsTableField(name,maxIndex + 1,column,null,null) + if self.ShowHeaderRow then + newField.HeaderCell(cellsCollection,true).SetValueAs name |> ignore + _fieldNames.Add(name,newField) + self.RescanRange() + newField + /// Takes a name of an FsTableField and an FsCellsCollection (belonging to the FsWorksheet of this FsTable) and returns the respective FsTableField. /// if the header row has no field with the given name. - member self.Field(name : string, cells : FsCellsCollection) = + member self.GetField(name : string, cellsCollection : FsCellsCollection) = let name = name.Replace("\r\n", "\n") - try self.FieldNames(cells).Item name + try self.FieldNames(cellsCollection).Item name with _ -> failwith <| "The header row doesn't contain field name '" + name + "'." - // TO DO: ask HLW: why this way? - ///// Returns the FsTableField with given name. If an FsTableField does not exist under this name in the FsTable, adds it. - //member self.Field(name, cells : FsCellsCollection) = - //match Dictionary.tryGet name _fieldNames with - //| Some field -> - // field - //| None -> - // let maxIndex = - // _fieldNames.Values - // |> Seq.map (fun v -> v.Index) - // |> fun s -> - // if Seq.length s = 0 then 0 else Seq.max s - // let range = - // let offset = _fieldNames.Count - // let firstAddress = FsAddress(self.RangeAddress.FirstAddress.RowNumber,self.RangeAddress.FirstAddress.ColumnNumber + offset) - // let lastAddress = FsAddress(self.RangeAddress.LastAddress.RowNumber,self.RangeAddress.FirstAddress.ColumnNumber + offset) - // FsRangeAddress(firstAddress,lastAddress) - // let column = FsRangeColumn(range) - // let newField = FsTableField(name,maxIndex + 1,column,null,null) - // if self.ShowHeaderRow then - // newField.HeaderCell(cells,true).SetValueAs name |> ignore - // _fieldNames.Add(name,newField) - // self.RescanRange() - // newField + /// Takes a name of an FsTableField and an FsCellsCollection (belonging to the FsWorksheet of this FsTable) and returns the respective FsTableField. + /// if the header row has no field with the given name. + static member getFieldByName (name : string) (cellsCollection : FsCellsCollection) (table : FsTable) = + table.GetField(name, cellsCollection) /// Takes the index of an FsTableField and an FsCellsCollection (belonging to the FsWorksheet of this FsTable) and returns the respective FsTableField. /// if the FsTable has no FsTableField with the given index. - member self.Field(index, cells) = + member self.GetField(index, cellsCollection) = try - self.FieldNames(cells).Values + self.FieldNames(cellsCollection).Values |> Seq.find (fun ftf -> ftf.Index = index) with _ -> failwith $"FsTableField with index {index} does not exist in the FsTable." /// Takes a name of an FsTableField and an FsCellsCollection (belonging to the FsWorksheet of this FsTable) and returns the index of the respective FsTableField. /// if the header row has no field with the given name. - member self.GetFieldIndex(name : string, cells) = - self.Field(name, cells).Index + member self.GetFieldIndex(name : string, cellsCollection) = + self.GetField(name, cellsCollection).Index + /// Renames a fieldname of the FsTable if it exists. Else fails. + /// if the FsTableField does not exist in the FsTable. member this.RenameField(oldName : string, newName : string) = match Dictionary.tryGet oldName _fieldNames with | Some field -> _fieldNames.Remove(oldName) |> ignore _fieldNames.Add(newName, field) | None -> - raise (System.ArgumentException("The field does not exist in this table", "oldName")) \ No newline at end of file + raise (System.ArgumentException("The FsTabelField does not exist in this FsTable", "oldName")) + + /// Renames a fieldname of the FsTable if it exists. Else fails. + /// if the FsTableField does not exist in the FsTable. + static member renameField oldName newName (table : FsTable) = + table.RenameField(oldName, newName) \ No newline at end of file