Skip to content

Commit

Permalink
hotfix table not written correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
HLWeil committed Jul 31, 2023
1 parent 1fd0e34 commit 5293ae9
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/FsSpreadsheet.ExcelIO/FsExtensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ module FsExtensions =
/// Returns the FsTable with given FsCellsCollection in the form of an XlsxTable.
/// </summary>
member self.ToXlsxTable(cells : FsCellsCollection) =

self.RescanFieldNames cells
let columns =
self.GetFieldNames(cells)
|> Seq.map (fun kv ->
Expand Down
46 changes: 44 additions & 2 deletions src/FsSpreadsheet/Tables/FsTable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type FsTable (name : string, rangeAddress : FsRangeAddress, ?showTotalsRow : boo

inherit FsRangeBase(rangeAddress)

let mutable _name = name
let mutable _name = name.Trim().Replace(" ","_")

let mutable _lastRangeAddress = rangeAddress
let mutable _showTotalsRow : bool = Option.defaultValue false showTotalsRow
Expand Down Expand Up @@ -396,4 +396,46 @@ type FsTable (name : string, rangeAddress : FsRangeAddress, ?showTotalsRow : boo
/// Returns a deep copy of a given FsTable.
/// </summary>
static member copy (table : FsTable) =
table.Copy()
table.Copy()


/// Updates the TableFields according to the range of the table and the underlying cellcollection.
///
/// For this, maps over the range of the table and sets the header of the table fields to the value of the cell. If no cell value is set, the header value and the underlying cell value are set to a default value.
member this.RescanFieldNames(cellsCollection : FsCellsCollection) =
if this.ShowHeaderRow then
let oldFieldNames = _fieldNames
_fieldNames <- new Dictionary<string, FsTableField>()
let headersRow = this.HeadersRow();
let mutable cellPos = 0
for cell in headersRow.Cells(cellsCollection) do
let mutable name = cell.Value //GetString();
match Dictionary.tryGet name oldFieldNames with
| Some tableField ->
tableField.Index <- cellPos
_fieldNames.Add(name,tableField)
cellPos <- cellPos + 1
| None ->

// Be careful here. Fields names may actually be whitespace, but not empty
if (name = null) <> (name = "") then // TO DO: ask: shouldn't this be XOR?

name <- this.GetUniqueName("Column", cellPos + 1, true)
cell.SetValueAs(name) |> ignore
cell.DataType <- DataType.String

if (_fieldNames.ContainsKey(name)) then
raise (System.ArgumentException("The header row contains more than one field name '" + name + "'."))

_fieldNames.Add(name, new FsTableField(name, cellPos))
cellPos <- cellPos + 1
else

let colCount = base.ColumnCount();
for i = 1 to colCount do

if _fieldNames.Values |> Seq.exists (fun v -> v.Index = i - 1) |> not then

let name = "Column" + string i;

_fieldNames.Add(name, new FsTableField(name, i - 1));
51 changes: 51 additions & 0 deletions tests/FsSpreadsheet.ExcelIO.Tests/Table.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,57 @@ let transformTable =
Expect.isTrue (table.TotalsRowShown = null) "Check that field of interest is None"
FsTable.fromXlsxTable table |> ignore
)
testCase "InfersTableColumnsFromRange" (fun () ->

// --- Prepare Table ---
let wb = new FsWorkbook()

let ws = wb.InitWorksheet("New Worksheet")

let columnNames = [|"My Column 1";"My Column 2"|]

ws.AddCell(FsCell(columnNames.[0],address=FsAddress("B1"))) |> ignore
ws.AddCell(FsCell(columnNames.[1],address=FsAddress("C1"))) |> ignore
let t = FsTable("My_New_Table", FsRangeAddress("B1:C2"))

ws.AddTable(t) |> ignore

// --- Function of interest ---

let bytes = wb.ToBytes()

// --- Get Tables ---

let ms = new System.IO.MemoryStream(bytes)

let doc = Spreadsheet.fromStream ms false
let xlsxWorkbookPart = Spreadsheet.getWorkbookPart doc

let tables =
Workbook.get xlsxWorkbookPart
|> Sheet.Sheets.get
|> Sheet.Sheets.getSheets
|> Seq.collect (
fun s ->
let sid = Sheet.getID s
Worksheet.WorksheetPart.getByID sid xlsxWorkbookPart
|> Worksheet.WorksheetPart.getTables
)


// --- Checks ---
Expect.equal (Seq.length tables) 1 "Check that there is one table"

let table = Seq.head tables
let tableColumnNames =
table.TableColumns
|> Table.TableColumns.getTableColumns
|> Seq.map (fun tc -> Table.TableColumn.getName tc)

Expect.sequenceEqual tableColumnNames columnNames "Check that column names match"


)

]

Expand Down

0 comments on commit 5293ae9

Please sign in to comment.