diff --git a/src/FsSpreadsheet.Js/FsExtensions.fs b/src/FsSpreadsheet.Js/FsExtensions.fs index 9702b28..5eaecbc 100644 --- a/src/FsSpreadsheet.Js/FsExtensions.fs +++ b/src/FsSpreadsheet.Js/FsExtensions.fs @@ -43,8 +43,8 @@ type FsWorkbook with static member fromRowsJsonString (json:string) : FsWorkbook = Json.fromRowsJsonString json - static member toRowsJsonString (wb:FsWorkbook) : string = - Json.toRowsJsonString wb + static member toRowsJsonString (wb:FsWorkbook,?spaces, ?noNumbering) : string = + Json.toRowsJsonString(wb, ?spaces = spaces, ?noNumbering = noNumbering) //static member fromJsonFile (path:string) : Promise = // Json.fromJsonFile path @@ -55,15 +55,15 @@ type FsWorkbook with //member this.ToJsonFile(path: string) : Promise = // FsWorkbook.toJsonFile path this - member this.ToRowsJsonString() : string = - FsWorkbook.toRowsJsonString this + member this.ToRowsJsonString(?spaces, ?noNumbering) : string = + FsWorkbook.toRowsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering) static member fromColumnsJsonString (json:string) : FsWorkbook = Json.fromColumnsJsonString json - static member toColumnsJsonString (wb:FsWorkbook) : string = - Json.toColumnsJsonString wb + static member toColumnsJsonString (wb:FsWorkbook,?spaces, ?noNumbering) : string = + Json.toColumnsJsonString(wb, ?spaces = spaces, ?noNumbering = noNumbering) - member this.ToColumnsJsonString() : string = - FsWorkbook.toColumnsJsonString this \ No newline at end of file + member this.ToColumnsJsonString(?spaces, ?noNumbering) : string = + FsWorkbook.toColumnsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering) \ No newline at end of file diff --git a/src/FsSpreadsheet.Js/Json.fs b/src/FsSpreadsheet.Js/Json.fs index dd1efff..01d96ee 100644 --- a/src/FsSpreadsheet.Js/Json.fs +++ b/src/FsSpreadsheet.Js/Json.fs @@ -26,9 +26,10 @@ type Json = | Ok wb -> wb | Error e -> failwithf "Could not deserialize json Workbook: \n%s" e - static member toRowsJsonString (wb:FsWorkbook, ?spaces) : string = + static member toRowsJsonString (wb:FsWorkbook, ?spaces, ?noNumbering) : string = let spaces = defaultArg spaces 2 - FsSpreadsheet.Json.Workbook.encodeRows wb + let noNumbering = defaultArg noNumbering false + FsSpreadsheet.Json.Workbook.encodeRows noNumbering wb |> Thoth.Json.JavaScript.Encode.toString spaces static member tryFromColumnsJsonString (json:string) : Result = @@ -41,9 +42,10 @@ type Json = | Ok wb -> wb | Error e -> failwithf "Could not deserialize json Workbook: \n%s" e - static member toColumnsJsonString (wb:FsWorkbook, ?spaces) : string = + static member toColumnsJsonString (wb:FsWorkbook, ?spaces, ?noNumbering) : string = let spaces = defaultArg spaces 2 - FsSpreadsheet.Json.Workbook.encodeColumns wb + let noNumbering = defaultArg noNumbering false + FsSpreadsheet.Json.Workbook.encodeColumns noNumbering wb |> Thoth.Json.JavaScript.Encode.toString spaces //static member fromJsonFile (path:string) : Promise = diff --git a/src/FsSpreadsheet.Net/FsExtensions.fs b/src/FsSpreadsheet.Net/FsExtensions.fs index 6451cf4..96d4e37 100644 --- a/src/FsSpreadsheet.Net/FsExtensions.fs +++ b/src/FsSpreadsheet.Net/FsExtensions.fs @@ -319,14 +319,6 @@ module FsExtensions = let bytes = File.ReadAllBytes filePath FsWorkbook.fromXlsxBytes bytes - /// - /// Takes the path to an Xlsx file and returns the FsWorkbook based on its content. - /// - [] - static member fromFile (filePath : string) = - let bytes = File.ReadAllBytes filePath - FsWorkbook.fromXlsxBytes bytes - /// /// Takes a json string and returns the FsWorkbook based on its content. /// @@ -436,58 +428,45 @@ module FsExtensions = self.ToXlsxBytes() |> fun bytes -> File.WriteAllBytes (path, bytes) - /// - /// Writes the FsWorkbook into a binary file at the given path. - /// - [] - member self.ToFile(path) = - self.ToXlsxBytes() - |> fun bytes -> File.WriteAllBytes (path, bytes) - /// /// Writes an FsWorkbook into a binary file at the given path. /// static member toXlsxFile path (workbook : FsWorkbook) = workbook.ToXlsxFile(path) - /// - /// Takes the path to an Xlsx file and returns the FsWorkbook based on its content. - /// - [] - static member toFile (filePath : string) path (workbook : FsWorkbook) = - workbook.ToXlsxFile(path) - - static member toRowsJsonString (workbook : FsWorkbook, ?spaces) = + static member toRowsJsonString (workbook : FsWorkbook, ?spaces, ?noNumbering) = let spaces = defaultArg spaces 2 - FsSpreadsheet.Json.Workbook.encodeRows workbook + let noNumbering = defaultArg noNumbering false + FsSpreadsheet.Json.Workbook.encodeRows noNumbering workbook |> Thoth.Json.Newtonsoft.Encode.toString spaces - static member toRowsJsonFile (path, ?spaces) = + static member toRowsJsonFile (path, ?spaces, ?noNumbering) = fun workbook -> - let json = FsWorkbook.toRowsJsonString (workbook,?spaces = spaces) + let json = FsWorkbook.toRowsJsonString (workbook,?spaces = spaces, ?noNumbering = noNumbering) File.WriteAllText(path,json) - member this.ToRowsJsonString(?spaces) = - FsWorkbook.toRowsJsonString(this, ?spaces = spaces) + member this.ToRowsJsonString(?spaces, ?noNumbering) = + FsWorkbook.toRowsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering) - member this.ToRowsJsonFile(path: string, ?spaces) = - FsWorkbook.toRowsJsonFile(path, ?spaces = spaces) this + member this.ToRowsJsonFile(path: string, ?spaces, ?noNumbering) = + FsWorkbook.toRowsJsonFile(path, ?spaces = spaces, ?noNumbering = noNumbering) this - static member toColumnsJsonString (workbook : FsWorkbook, ?spaces) = + static member toColumnsJsonString (workbook : FsWorkbook, ?spaces, ?noNumbering) = + let noNumbering = defaultArg noNumbering false let spaces = defaultArg spaces 2 - FsSpreadsheet.Json.Workbook.encodeColumns workbook + FsSpreadsheet.Json.Workbook.encodeColumns noNumbering workbook |> Thoth.Json.Newtonsoft.Encode.toString spaces - static member toColumnsJsonFile (path, ?spaces) = + static member toColumnsJsonFile (path, ?spaces, ?noNumbering) = fun workbook -> - let json = FsWorkbook.toColumnsJsonString (workbook,?spaces = spaces) + let json = FsWorkbook.toColumnsJsonString (workbook,?spaces = spaces, ?noNumbering = noNumbering) File.WriteAllText(path,json) - member this.ToColumnsJsonString(?spaces) = - FsWorkbook.toColumnsJsonString(this, ?spaces = spaces) + member this.ToColumnsJsonString(?spaces, ?noNumbering) = + FsWorkbook.toColumnsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering) - member this.ToColumnsJsonFile(path: string, ?spaces) = - FsWorkbook.toColumnsJsonFile(path, ?spaces = spaces) this + member this.ToColumnsJsonFile(path: string, ?spaces, ?noNumbering) = + FsWorkbook.toColumnsJsonFile(path, ?spaces = spaces, ?noNumbering = noNumbering) this type Writer = diff --git a/src/FsSpreadsheet.Py/FsExtension.fs b/src/FsSpreadsheet.Py/FsExtension.fs index 13a3c6c..81034e5 100644 --- a/src/FsSpreadsheet.Py/FsExtension.fs +++ b/src/FsSpreadsheet.Py/FsExtension.fs @@ -39,8 +39,8 @@ type FsWorkbook with static member fromRowsJsonString (json:string) : FsWorkbook = Json.fromRowsJsonString json - static member toRowsJsonString (wb:FsWorkbook) : string = - Json.toRowsJsonString wb + static member toRowsJsonString (wb:FsWorkbook,?spaces,?noNumbering) : string = + Json.toRowsJsonString(wb, ?spaces = spaces, ?noNumbering = noNumbering) //static member fromJsonFile (path:string) : Promise = // Json.fromJsonFile path @@ -51,15 +51,15 @@ type FsWorkbook with //member this.ToJsonFile(path: string) : Promise = // FsWorkbook.toJsonFile path this - member this.ToRowsJsonString() : string = - FsWorkbook.toRowsJsonString this + member this.ToRowsJsonString(?spaces,?noNumbering) : string = + FsWorkbook.toRowsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering) static member fromColumnsJsonString (json:string) : FsWorkbook = Json.fromColumnsJsonString json - static member toColumnsJsonString (wb:FsWorkbook) : string = - Json.toColumnsJsonString wb + static member toColumnsJsonString (wb:FsWorkbook,?spaces,?noNumbering) : string = + Json.toColumnsJsonString(wb, ?spaces = spaces, ?noNumbering = noNumbering) - member this.ToColumnsJsonString() : string = - FsWorkbook.toColumnsJsonString this + member this.ToColumnsJsonString(?spaces,?noNumbering) : string = + FsWorkbook.toColumnsJsonString(this, ?spaces = spaces, ?noNumbering = noNumbering) \ No newline at end of file diff --git a/src/FsSpreadsheet.Py/Json.fs b/src/FsSpreadsheet.Py/Json.fs index 64f54c3..f9bb9d6 100644 --- a/src/FsSpreadsheet.Py/Json.fs +++ b/src/FsSpreadsheet.Py/Json.fs @@ -23,9 +23,10 @@ type Json = | Ok wb -> wb | Error e -> failwithf "Could not deserialize json Workbook: \n%s" e - static member toRowsJsonString (wb:FsWorkbook, ?spaces) : string = + static member toRowsJsonString (wb:FsWorkbook, ?spaces, ?noNumbering) : string = + let noNumbering = defaultArg noNumbering false let spaces = defaultArg spaces 2 - FsSpreadsheet.Json.Workbook.encodeRows wb + FsSpreadsheet.Json.Workbook.encodeRows noNumbering wb |> Encode.toString spaces static member tryFromColumnsJsonString (json:string) : Result = @@ -36,7 +37,8 @@ type Json = | Ok wb -> wb | Error e -> failwithf "Could not deserialize json Workbook: \n%s" e - static member toColumnsJsonString (wb:FsWorkbook, ?spaces) : string = + static member toColumnsJsonString (wb:FsWorkbook, ?spaces, ?noNumbering) : string = let spaces = defaultArg spaces 2 - FsSpreadsheet.Json.Workbook.encodeColumns wb + let noNumbering = defaultArg noNumbering false + FsSpreadsheet.Json.Workbook.encodeColumns noNumbering wb |> Encode.toString spaces \ No newline at end of file diff --git a/src/FsSpreadsheet/FsWorksheet.fs b/src/FsSpreadsheet/FsWorksheet.fs index c9bcc8a..6a076fd 100644 --- a/src/FsSpreadsheet/FsWorksheet.fs +++ b/src/FsSpreadsheet/FsWorksheet.fs @@ -81,6 +81,10 @@ type FsWorksheet (name, ?fsRows, ?fsTables, ?fsCellsCollection) = FsColumn(newRange,self.CellCollection) ) + member this.MaxRowIndex = this.CellCollection.MaxRowNumber + + member this.MaxColumnIndex = this.CellCollection.MaxColumnNumber + // ------- // METHODS // ------- diff --git a/src/FsSpreadsheet/Json/Cell.fs b/src/FsSpreadsheet/Json/Cell.fs index babbfe9..efd3451 100644 --- a/src/FsSpreadsheet/Json/Cell.fs +++ b/src/FsSpreadsheet/Json/Cell.fs @@ -12,6 +12,11 @@ let row = "row" [] let value = "value" +let encodeNoNumber (cell:FsCell) = + Encode.object [ + value, Value.encode cell.Value + ] + let encodeRows (cell:FsCell) = Encode.object [ column, Encode.int cell.ColumnNumber @@ -34,7 +39,7 @@ let encodeCols (cell:FsCell) = let decodeCols colNumber : Decoder = Decode.object (fun builder -> - let v,dt = builder.Required.Field value (Value.decode) - let r = builder.Required.Field row Decode.int - new FsCell(v,dt,FsAddress(r,colNumber)) + let v,dt = builder.Optional.Field value (Value.decode) |> Option.defaultValue ("", DataType.Empty) + let r = builder.Optional.Field row Decode.int |> Option.defaultValue 0 + new FsCell(v,dt,FsAddress(r,Option.defaultValue 0 colNumber)) ) diff --git a/src/FsSpreadsheet/Json/Column.fs b/src/FsSpreadsheet/Json/Column.fs index ed40b64..1764777 100644 --- a/src/FsSpreadsheet/Json/Column.fs +++ b/src/FsSpreadsheet/Json/Column.fs @@ -15,9 +15,14 @@ let encode (col:FsColumn) = cells, Encode.seq (col.Cells |> Seq.map Cell.encodeCols) ] -let decode : Decoder = +let encodeNoNumbers (col: FsCell seq) = + Encode.object [ + cells, Encode.seq (col |> Seq.map Cell.encodeNoNumber) + ] + +let decode : Decoder = Decode.object (fun builder -> - let n = builder.Required.Field number Decode.int - let cs = builder.Required.Field cells (Decode.seq (Cell.decodeCols n)) + let n = builder.Optional.Field number Decode.int + let cs = builder.Optional.Field cells (Decode.seq (Cell.decodeCols n)) |> Option.defaultValue Seq.empty n,cs ) \ No newline at end of file diff --git a/src/FsSpreadsheet/Json/Row.fs b/src/FsSpreadsheet/Json/Row.fs index 5fcdd50..f241cb1 100644 --- a/src/FsSpreadsheet/Json/Row.fs +++ b/src/FsSpreadsheet/Json/Row.fs @@ -15,6 +15,11 @@ let encode (row:FsRow) = cells, Encode.seq (row.Cells |> Seq.map Cell.encodeRows) ] +let encodeNoNumbers (row: FsCell seq) = + Encode.object [ + cells, Encode.seq (row |> Seq.map Cell.encodeNoNumber) + ] + let decode : Decoder = Decode.object (fun builder -> let n = builder.Optional.Field number Decode.int diff --git a/src/FsSpreadsheet/Json/Workbook.fs b/src/FsSpreadsheet/Json/Workbook.fs index 1617ed1..e348dae 100644 --- a/src/FsSpreadsheet/Json/Workbook.fs +++ b/src/FsSpreadsheet/Json/Workbook.fs @@ -6,9 +6,9 @@ open Thoth.Json.Core [] let sheets = "sheets" -let encodeRows (wb:FsWorkbook) = +let encodeRows noNumbering (wb:FsWorkbook) = Encode.object [ - sheets, Encode.seq (wb.GetWorksheets() |> Seq.map Worksheet.encodeRows) + sheets, Encode.seq (wb.GetWorksheets() |> Seq.map (Worksheet.encodeRows noNumbering)) ] let decodeRows : Decoder = @@ -19,9 +19,9 @@ let decodeRows : Decoder = wb ) -let encodeColumns (wb:FsWorkbook) = +let encodeColumns noNumbering (wb:FsWorkbook) = Encode.object [ - sheets, Encode.seq (wb.GetWorksheets() |> Seq.map Worksheet.encodeColumns) + sheets, Encode.seq (wb.GetWorksheets() |> Seq.map (Worksheet.encodeColumns noNumbering)) ] let decodeColumns : Decoder = diff --git a/src/FsSpreadsheet/Json/Worksheet.fs b/src/FsSpreadsheet/Json/Worksheet.fs index c285c72..10dc3a3 100644 --- a/src/FsSpreadsheet/Json/Worksheet.fs +++ b/src/FsSpreadsheet/Json/Worksheet.fs @@ -15,13 +15,31 @@ let columns = "columns" [] let tables = "tables" -let encodeRows (sheet:FsWorksheet) = +let encodeRows noNumbering (sheet:FsWorksheet) = + sheet.RescanRows() + let jRows = + if noNumbering then + [ + for r = 1 to sheet.MaxRowIndex do + [ + for c = 1 to sheet.MaxColumnIndex do + match sheet.CellCollection.TryGetCell(r,c) with + | Some cell -> cell + | None -> new FsCell("") + + ] + |> Row.encodeNoNumbers + ] + |> Encode.seq + else + Encode.seq (sheet.Rows |> Seq.map Row.encode) + Encode.object [ name, Encode.string sheet.Name if Seq.isEmpty sheet.Tables |> not then tables, Encode.seq (sheet.Tables |> Seq.map Table.encode) - rows, Encode.seq (sheet.Rows |> Seq.map Row.encode) + rows, jRows ] @@ -64,27 +82,57 @@ let decodeRows : Decoder = sheet ) -let encodeColumns (sheet:FsWorksheet) = +let encodeColumns noNumbering (sheet:FsWorksheet) = sheet.RescanRows() + + let jColumns = + if noNumbering then + [ + for c = 1 to sheet.MaxColumnIndex do + [ + for r = 1 to sheet.MaxRowIndex do + match sheet.CellCollection.TryGetCell(r,c) with + | Some cell -> cell + | None -> new FsCell("") + + ] + |> Column.encodeNoNumbers + ] + |> Encode.seq + else + Encode.seq (sheet.Columns |> Seq.map Column.encode) + Encode.object [ name, Encode.string sheet.Name if Seq.isEmpty sheet.Tables |> not then tables, Encode.seq (sheet.Tables |> Seq.map Table.encode) - columns, Encode.seq (sheet.Columns |> Seq.map Column.encode) + columns, jColumns ] let decodeColumns : Decoder = Decode.object (fun builder -> + let mutable colIndex = 0 let n = builder.Required.Field name Decode.string let ts = builder.Optional.Field tables (Decode.seq Table.decode) let cs = builder.Required.Field columns (Decode.seq Column.decode) let sheet = new FsWorksheet(n) cs |> Seq.iter (fun (colI,cells) -> + let mutable rowIndex = 0 + let colI = + match colI with + | Some i -> i + | None -> colIndex + 1 + colIndex <- colI let col = sheet.Column(colI) cells - |> Seq.iter (fun cell -> - let c = col[cell.RowNumber] + |> Seq.iter (fun cell -> + let rowI = + match cell.RowNumber with + | 0 -> rowIndex + 1 + | i -> i + rowIndex <- rowI + let c = col[rowIndex] c.Value <- cell.Value c.DataType <- cell.DataType ) diff --git a/tests/FsSpreadsheet.Js.Tests/Json.Tests.fs b/tests/FsSpreadsheet.Js.Tests/Json.Tests.fs index 5e487f3..896999e 100644 --- a/tests/FsSpreadsheet.Js.Tests/Json.Tests.fs +++ b/tests/FsSpreadsheet.Js.Tests/Json.Tests.fs @@ -5,10 +5,22 @@ open FsSpreadsheet open FsSpreadsheet.Js open Fable.Pyxpecto +let getFilledTestWb() = + let wb = new FsWorkbook() + let ws = FsWorkbook.initWorksheet "MySheet" wb + let r1 = ws.Row(1) + r1.[1].SetValueAs "A1" + r1.[2].SetValueAs "B1" + let r2 = ws.Row(2) + r2.[1].SetValueAs "A2" + r2.[2].SetValueAs "B2" + wb + + let rows = testList "Rows" [ - - testCase "Read Standard" <| fun _ -> + // Dependent on https://github.com/fable-compiler/Fable/issues/3858 + ptestCase "Standard Read" <| fun _ -> // Read object taken from https://spreadsheet.dsl.builders/#_sheets_and_rows let s = """{ "sheets": [ @@ -19,7 +31,7 @@ let rows = "number": 5, "cells": [ { - "value": "Line Number Five" + "value": "Line 5" } ] }, @@ -28,7 +40,7 @@ let rows = { "cells": [ { - "value": "Line Number Seven" + "value": "Line 7" } ] } @@ -43,7 +55,7 @@ let rows = Expect.isTrue (sheet.ContainsRowAt 5) "Row 5" let row1 = sheet.Row(5) Expect.isTrue (row1.HasCellAt 1) "Row 5 cell" - Expect.equal (row1.[1].Value) "Line Number Five" "Row 5 cell value" + Expect.equal (row1.[1].Value) "Line 5" "Row 5 cell value" Expect.isTrue (sheet.ContainsRowAt 6) "Row 6" let row1 = sheet.Row(6) @@ -52,9 +64,55 @@ let rows = Expect.isTrue (sheet.ContainsRowAt 7) "Row 7" let row2 = sheet.Row(7) Expect.isTrue (row2.HasCellAt 1) "Row 7 cell" - Expect.equal (row2.[1].Value) "Line Number Seven" "Row 7 cell value" + Expect.equal (row2.[1].Value) "Line 7" "Row 7 cell value" + + testCase "NoNumber Filled Write" <| fun _ -> + let wb = getFilledTestWb() + let expectedString = """{ + "sheets": [ + { + "name": "MySheet", + "rows": [ + { + "cells": [ + { + "value": "A1" + }, + { + "value": "B1" + } + ] + }, + { + "cells": [ + { + "value": "A2" + }, + { + "value": "B2" + } + ] + } + ] + } + ] +}""" + let s = wb.ToRowsJsonString(noNumbering = true) + Expect.stringEqual s expectedString "NoNumber Filled Write-Read" + + testCase "NoNumber Filled Write-Read" <| fun _ -> + let wb = getFilledTestWb() + let s = wb.ToRowsJsonString(noNumbering = true) + let wb2 = FsWorkbook.fromRowsJsonString(s) + Expect.workSheetEqual (wb2.GetWorksheetAt(1)) (wb.GetWorksheetAt(1)) "NoNumber Filled Write-Read" + + testCase "NoNumber DefaultTestObject Write-Read_Success" <| fun _ -> + let dto = DefaultTestObject.defaultTestObject() + let s = dto.ToRowsJsonString(noNumbering = true) + let dto2 = FsWorkbook.fromRowsJsonString(s) + () - testCase "Read-Write DefaultTestObject" <| fun _ -> + testCase "DefaultTestObject Write-Read" <| fun _ -> let dto = DefaultTestObject.defaultTestObject() let s = dto.ToRowsJsonString() let dto2 = FsWorkbook.fromRowsJsonString(s) @@ -64,12 +122,57 @@ let rows = let columns = testList "Columns" [ - testCase "Read-Write DefaultTestObject" <| fun _ -> + testCase "NoNumber Filled Write" <| fun _ -> + let wb = getFilledTestWb() + let expectedString = """{ + "sheets": [ + { + "name": "MySheet", + "columns": [ + { + "cells": [ + { + "value": "A1" + }, + { + "value": "A2" + } + ] + }, + { + "cells": [ + { + "value": "B1" + }, + { + "value": "B2" + } + ] + } + ] + } + ] +}""" + let s = wb.ToColumnsJsonString(noNumbering = true) + Expect.stringEqual s expectedString "NoNumber Filled Write-Read" + + testCase "NoNumber Filled Write-Read" <| fun _ -> + let wb = getFilledTestWb() + let s = wb.ToColumnsJsonString(noNumbering = true) + let wb2 = FsWorkbook.fromColumnsJsonString(s) + Expect.workSheetEqual (wb2.GetWorksheetAt(1)) (wb.GetWorksheetAt(1)) "NoNumber Filled Write-Read" + + testCase "NoNumber DefaultTestObject Write-Read_Success" <| fun _ -> + let dto = DefaultTestObject.defaultTestObject() + let s = dto.ToColumnsJsonString(noNumbering = true) + let dto2 = FsWorkbook.fromColumnsJsonString(s) + () + + testCase "DefaultTestObject Write-Read" <| fun _ -> let dto = DefaultTestObject.defaultTestObject() let s = dto.ToColumnsJsonString() let dto2 = FsWorkbook.fromColumnsJsonString(s) Expect.isDefaultTestObject dto2 - ] let main = testList "Json" [ diff --git a/tests/FsSpreadsheet.Net.Tests/Json.Tests.fs b/tests/FsSpreadsheet.Net.Tests/Json.Tests.fs index c797d9d..091e48f 100644 --- a/tests/FsSpreadsheet.Net.Tests/Json.Tests.fs +++ b/tests/FsSpreadsheet.Net.Tests/Json.Tests.fs @@ -5,6 +5,17 @@ open FsSpreadsheet open FsSpreadsheet.Net open Fable.Pyxpecto +let getFilledTestWb() = + let wb = new FsWorkbook() + let ws = FsWorkbook.initWorksheet "MySheet" wb + let r1 = ws.Row(1) + r1.[1].SetValueAs "A1" + r1.[2].SetValueAs "B1" + let r2 = ws.Row(2) + r2.[1].SetValueAs "A2" + r2.[2].SetValueAs "B2" + wb + let rows = testList "Rows" [ testCase "Read Standard" <| fun _ -> @@ -53,7 +64,53 @@ let rows = Expect.isTrue (row2.HasCellAt 1) "Row 7 cell" Expect.equal (row2.[1].Value) "Line 7" "Row 7 cell value" - testCase "Read-Write DefaultTestObject" <| fun _ -> + testCase "NoNumber Filled Write" <| fun _ -> + let wb = getFilledTestWb() + let expectedString = """{ + "sheets": [ + { + "name": "MySheet", + "rows": [ + { + "cells": [ + { + "value": "A1" + }, + { + "value": "B1" + } + ] + }, + { + "cells": [ + { + "value": "A2" + }, + { + "value": "B2" + } + ] + } + ] + } + ] +}""" + let s = wb.ToRowsJsonString(noNumbering = true) + Expect.stringEqual s expectedString "NoNumber Filled Write-Read" + + testCase "NoNumber Filled Write-Read" <| fun _ -> + let wb = getFilledTestWb() + let s = wb.ToRowsJsonString(noNumbering = true) + let wb2 = FsWorkbook.fromRowsJsonString(s) + Expect.workSheetEqual (wb2.GetWorksheetAt(1)) (wb.GetWorksheetAt(1)) "NoNumber Filled Write-Read" + + testCase "NoNumber DefaultTestObject Write-Read_Success" <| fun _ -> + let dto = DefaultTestObject.defaultTestObject() + let s = dto.ToRowsJsonString(noNumbering = true) + let dto2 = FsWorkbook.fromRowsJsonString(s) + () + + testCase "Write-Read DefaultTestObject" <| fun _ -> let dto = DefaultTestObject.defaultTestObject() let s = dto.ToRowsJsonString() System.IO.File.WriteAllText(DefaultTestObject.FsSpreadsheetJSON.asRelativePath,s) @@ -64,7 +121,53 @@ let rows = let columns = testList "Columns" [ - testCase "Read-Write DefaultTestObject" <| fun _ -> + testCase "NoNumber Filled Write" <| fun _ -> + let wb = getFilledTestWb() + let expectedString = """{ + "sheets": [ + { + "name": "MySheet", + "columns": [ + { + "cells": [ + { + "value": "A1" + }, + { + "value": "A2" + } + ] + }, + { + "cells": [ + { + "value": "B1" + }, + { + "value": "B2" + } + ] + } + ] + } + ] +}""" + let s = wb.ToColumnsJsonString(noNumbering = true) + Expect.stringEqual s expectedString "NoNumber Filled Write-Read" + + testCase "NoNumber Filled Write-Read" <| fun _ -> + let wb = getFilledTestWb() + let s = wb.ToColumnsJsonString(noNumbering = true) + let wb2 = FsWorkbook.fromColumnsJsonString(s) + Expect.workSheetEqual (wb2.GetWorksheetAt(1)) (wb.GetWorksheetAt(1)) "NoNumber Filled Write-Read" + + testCase "NoNumber DefaultTestObject Write-Read_Success" <| fun _ -> + let dto = DefaultTestObject.defaultTestObject() + let s = dto.ToColumnsJsonString(noNumbering = true) + let dto2 = FsWorkbook.fromColumnsJsonString(s) + () + + testCase "DefaultTestObject Write-Read" <| fun _ -> let dto = DefaultTestObject.defaultTestObject() let s = dto.ToColumnsJsonString() System.IO.File.WriteAllText(DefaultTestObject.FsSpreadsheetJSON.asRelativePath,s) diff --git a/tests/FsSpreadsheet.Py.Tests/Json.Tests.fs b/tests/FsSpreadsheet.Py.Tests/Json.Tests.fs index 53b6fbf..f14275d 100644 --- a/tests/FsSpreadsheet.Py.Tests/Json.Tests.fs +++ b/tests/FsSpreadsheet.Py.Tests/Json.Tests.fs @@ -5,9 +5,21 @@ open FsSpreadsheet open FsSpreadsheet.Py open Fable.Pyxpecto +let getFilledTestWb() = + let wb = new FsWorkbook() + let ws = FsWorkbook.initWorksheet "MySheet" wb + let r1 = ws.Row(1) + r1.[1].SetValueAs "A1" + r1.[2].SetValueAs "B1" + let r2 = ws.Row(2) + r2.[1].SetValueAs "A2" + r2.[2].SetValueAs "B2" + wb + + let rows = testList "Rows" [ - testCase "Read Standard" <| fun _ -> + testCase "Standard Read" <| fun _ -> // Read object taken from https://spreadsheet.dsl.builders/#_sheets_and_rows let s = """{ "sheets": [ @@ -53,7 +65,53 @@ let rows = Expect.isTrue (row2.HasCellAt 1) "Row 7 cell" Expect.equal (row2.[1].Value) "Line 7" "Row 7 cell value" - testCase "Read-Write DefaultTestObject" <| fun _ -> + testCase "NoNumber Filled Write" <| fun _ -> + let wb = getFilledTestWb() + let expectedString = """{ + "sheets": [ + { + "name": "MySheet", + "rows": [ + { + "cells": [ + { + "value": "A1" + }, + { + "value": "B1" + } + ] + }, + { + "cells": [ + { + "value": "A2" + }, + { + "value": "B2" + } + ] + } + ] + } + ] +}""" + let s = wb.ToRowsJsonString(noNumbering = true) + Expect.stringEqual s expectedString "NoNumber Filled Write-Read" + + testCase "NoNumber Filled Write-Read" <| fun _ -> + let wb = getFilledTestWb() + let s = wb.ToRowsJsonString(noNumbering = true) + let wb2 = FsWorkbook.fromRowsJsonString(s) + Expect.workSheetEqual (wb2.GetWorksheetAt(1)) (wb.GetWorksheetAt(1)) "NoNumber Filled Write-Read" + + testCase "NoNumber DefaultTestObject Write-Read_Success" <| fun _ -> + let dto = DefaultTestObject.defaultTestObject() + let s = dto.ToRowsJsonString(noNumbering = true) + let dto2 = FsWorkbook.fromRowsJsonString(s) + () + + testCase "DefaultTestObject Write-Read" <| fun _ -> let dto = DefaultTestObject.defaultTestObject() let s = dto.ToRowsJsonString() let dto2 = FsWorkbook.fromRowsJsonString(s) @@ -63,7 +121,53 @@ let rows = let columns = testList "Columns" [ - testCase "Read-Write DefaultTestObject" <| fun _ -> + testCase "NoNumber Filled Write" <| fun _ -> + let wb = getFilledTestWb() + let expectedString = """{ + "sheets": [ + { + "name": "MySheet", + "columns": [ + { + "cells": [ + { + "value": "A1" + }, + { + "value": "A2" + } + ] + }, + { + "cells": [ + { + "value": "B1" + }, + { + "value": "B2" + } + ] + } + ] + } + ] +}""" + let s = wb.ToColumnsJsonString(noNumbering = true) + Expect.stringEqual s expectedString "NoNumber Filled Write-Read" + + testCase "NoNumber Filled Write-Read" <| fun _ -> + let wb = getFilledTestWb() + let s = wb.ToColumnsJsonString(noNumbering = true) + let wb2 = FsWorkbook.fromColumnsJsonString(s) + Expect.workSheetEqual (wb2.GetWorksheetAt(1)) (wb.GetWorksheetAt(1)) "NoNumber Filled Write-Read" + + testCase "NoNumber DefaultTestObject Write-Read_Success" <| fun _ -> + let dto = DefaultTestObject.defaultTestObject() + let s = dto.ToColumnsJsonString(noNumbering = true) + let dto2 = FsWorkbook.fromColumnsJsonString(s) + () + + testCase "DefaultTestObject Write-Read" <| fun _ -> let dto = DefaultTestObject.defaultTestObject() let s = dto.ToColumnsJsonString() let dto2 = FsWorkbook.fromColumnsJsonString(s) diff --git a/tests/TestUtils/TestingUtils.fs b/tests/TestUtils/TestingUtils.fs index f82457b..eb0eb70 100644 --- a/tests/TestUtils/TestingUtils.fs +++ b/tests/TestUtils/TestingUtils.fs @@ -6,6 +6,29 @@ open Fable.Core open Fable.Pyxpecto +module Fable = + + module JS = + + [] + let print (s:string) : unit = nativeOnly + + module Py = + + [] + let print (s:string) : unit = nativeOnly + + let fprint(s: string) = + #if FABLE_COMPILER_JAVASCRIPT + JS.print(s) + #endif + #if FABLE_COMPILER_PYTHON + Py.print(s) + #endif + #if !FABLE_COMPILER + printf "%s" s + #endif + [] module Utils = @@ -45,6 +68,33 @@ type Stopwatch() = /// Fable compatible Expecto/Mocha unification module Expect = + let inline equal actual expected message = Expect.equal actual expected message + let notEqual actual expected message = Expect.notEqual actual expected message + + /// + /// This function only verifies non-whitespace characters + /// + let stringEqual actual expected message = + let pattern = @"\s+" + let regex = System.Text.RegularExpressions.Regex(pattern, Text.RegularExpressions.RegexOptions.Singleline) + let actual = regex.Replace(actual, "") + let expected = regex.Replace(expected, "") + let mutable isSame = true + Seq.iter2 + (fun s1 s2 -> + if isSame && s1 = s2 then + () + elif isSame && s1 <> s2 then + isSame <- false + Fable.fprint (sprintf "%s" (string s1)) + else + Fable.fprint (sprintf "%s" (string s1)) + ) + actual + expected + equal actual expected message + + /// Expects the `actual` sequence to equal the `expected` one. let inline private _sequenceEqual message (comparison: int * 'a option * 'a option) = match comparison with @@ -111,7 +161,7 @@ module Expect = let workSheetEqual (actual : FsWorksheet) (expected : FsWorksheet) message = let f (ws : FsWorksheet) = ws.RescanRows() - ws.Rows |> Seq.map (fun r -> r.Cells) + ws.Rows |> Seq.map (fun r -> r.Cells |> Seq.filter (fun c -> c.Value <> "")) if actual.Name <> expected.Name then failwithf $"{message}. Worksheet names do not match. Expected {expected.Name} but got {actual.Name}" columnsEqual (f actual) (f expected) $"{message}. Worksheet does not match" @@ -133,9 +183,6 @@ module Expect = for actualRow, expectedRow in Seq.zip actualRows expectedRows do cellSequenceEquals actualRow expectedRow $"ExpectError: Worksheet rows are not equal for worksheet: {ws.Name}" - let inline equal actual expected message = Expect.equal actual expected message - let notEqual actual expected message = Expect.notEqual actual expected message - let isNull actual message = Expect.isNull actual message let isNotNull actual message = Expect.isNotNull actual message