Skip to content

Commit

Permalink
Fix ExcelIO: bool & float write. Fix exceljs: table postion write, ce…
Browse files Browse the repository at this point in the history
…ll value type read and write, confusing naming. Add scripts for fsspreadsheet write. ✨🤡
  • Loading branch information
Freymaurer committed Oct 24, 2023
1 parent 6fe7f89 commit 56d533f
Show file tree
Hide file tree
Showing 25 changed files with 272 additions and 205 deletions.
9 changes: 6 additions & 3 deletions src/FsSpreadsheet.ExcelIO/Cell.fs
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,12 @@ module Cell =
|> SharedStringTable.count
|> string
|> fun v -> {|DataType = Some CellValues.SharedString; Value = v; Format = None|}
| DataType.String -> {|DataType = Some CellValues.String; Value = value; Format = None|}
| DataType.Boolean -> {|DataType = Some CellValues.Boolean; Value = value; Format = None|}
| DataType.Number -> {|DataType = Some CellValues.Number; Value = value; Format = None|}
| DataType.String ->
{|DataType = Some CellValues.String; Value = value; Format = None|}
| DataType.Boolean ->
{|DataType = Some CellValues.Boolean; Value = System.Boolean.Parse value |> FsCellAux.boolConverter; Format = None|}
| DataType.Number ->
{|DataType = Some CellValues.Number; Value = value; Format = None|}
| DataType.Date ->
//let cellFormat = CellFormat(NumberFormatId = UInt32Value 19u, ApplyNumberFormat = BooleanValue true)
let value = System.DateTime.Parse(value).ToOADate() |> string
Expand Down
9 changes: 3 additions & 6 deletions src/FsSpreadsheet.ExcelIO/FsExtensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,10 @@ module FsExtensions =
| _ -> ()
| Number ->
try
cellValue <- int cellValueString
cellValue <- float cellValueString
with
| _ ->
try
cellValue <- float cellValueString
with
| _ -> ()
()
| Empty | String -> ()
//let dt, v = DataType.InferCellValue v
FsCell.createWithDataType dt (int row) (int col) (cellValue)
Expand Down Expand Up @@ -168,7 +165,7 @@ module FsExtensions =
let cells =
cells
|> List.map (fun cell ->
Cell.fromValueWithDataType doc (uint32 cell.ColumnNumber) (uint32 cell.RowNumber) (cell.ValueAsString()) (cell.DataType)
FsCell.toXlsxCell doc cell
)
let row = Row.create (uint32 row.Index) (Row.Spans.fromBoundaries min max) cells
SheetData.appendRow row sd |> ignore
Expand Down
88 changes: 88 additions & 0 deletions src/FsSpreadsheet.Exceljs/Cell.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
namespace FsSpreadsheet.Exceljs


module JsCell =

open Fable.Core
open Fable.Core.JsInterop
open FsSpreadsheet
open Fable.ExcelJs

[<Emit("console.log($0)")>]
let private log (obj:obj) = jsNative

let writeFromFsCell (fsCell: FsCell) =
match fsCell.DataType with
| Boolean ->
fsCell.ValueAsBool() |> box |> Some
| Number ->
fsCell.ValueAsFloat() |> box |> Some
| Date ->
/// Here it will actually show the correct DateTime. But when writing, exceljs will apply local offset.
let dt = fsCell.ValueAsDateTime() |> System.DateTimeOffset
/// Therefore we add offset and it should work.
let dt = dt + dt.Offset |> box |> Some
dt
| String ->
fsCell.Value |> Some
| anyElse ->
let msg = sprintf "ValueType '%A' is not fully implemented in FsSpreadsheet and is handled as string input." anyElse
#if FABLE_COMPILER_JAVASCRIPT
log msg
#else
printfn "%s" msg
#endif
fsCell.Value |> box |> Some

/// <summary>
/// `worksheetName`, `rowIndex` and `columnIndex` are only used for debugging.
/// </summary>
/// <param name="worksheetName"></param>
/// <param name="rowIndex"></param>
/// <param name="columnIndex"></param>
/// <param name="jsCell"></param>
let readToFsCell worksheetName rowIndex columnIndex (jsCell: Cell) =
let t = enum<Unions.ValueType>(jsCell.``type``)
let fsadress = FsAddress(jsCell.address)
let createFscell = fun dt v -> FsCell(v,dt,address = fsadress)
let vTemp = string jsCell.value.Value
let fscell =
match t with
| ValueType.Boolean ->
let b = System.Boolean.Parse vTemp
createFscell DataType.Boolean b
| ValueType.Number -> float vTemp |> createFscell DataType.Number
| ValueType.Date ->
let dt = System.DateTime.Parse(vTemp).ToUniversalTime()
/// Without this step universal time get changed to local time? Exceljs tests will hit this.
///
/// Expected item (from test object): C2 : Sat Oct 14 2023 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit) | Date
///
/// Actual item (created here): C2 : Sat Oct 14 2023 02:00:00 GMT+0200 (Mitteleuropäische Sommerzeit) | Date
///
/// But logging hour minute showed that the values were given correctly and needed to be reinitialized.
let dt = System.DateTime(dt.Year,dt.Month,dt.Day,dt.Hour,dt.Minute, dt.Second)
dt |> createFscell DataType.Date
| ValueType.String -> vTemp |> createFscell DataType.String
| ValueType.Formula ->
match jsCell.formula with
| "TRUE()" ->
let b = true
createFscell DataType.Boolean b
| "FALSE()" ->
let b = false
createFscell DataType.Boolean b
| anyElse ->
let msg = sprintf "ValueType 'Format' (%s) is not fully implemented in FsSpreadsheet and is handled as string input. In %s: (%i,%i)" anyElse worksheetName rowIndex columnIndex
log msg
anyElse |> createFscell DataType.String
| ValueType.Hyperlink ->
//log (c.value.Value?text)
jsCell.value.Value?hyperlink |> createFscell DataType.String
| anyElse ->
let msg = sprintf "ValueType `%A` (%s) is not fully implemented in FsSpreadsheet and is handled as string input. In %s: (%i,%i)" anyElse vTemp worksheetName rowIndex columnIndex
log msg
vTemp |> createFscell DataType.String
fscell


97 changes: 48 additions & 49 deletions src/FsSpreadsheet.Exceljs/FsSpreadsheet.Exceljs.fsproj
Original file line number Diff line number Diff line change
@@ -1,52 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Authors>Kevin Frey, Heinrich Lukas Weil, Oliver Maus, Kevin Schneider, Timo Mühlhaus</Authors>
<Description>Excel IO Extensions for the FsSpreadsheet Datamodel in js environments using exceljs.</Description>
<Summary>Spreadsheet creation and manipulation in FSharp</Summary>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageIcon>logo.png</PackageIcon>
<PackageTags>F# FSharp spreadsheet Excel xlsx datascience fable fable-library fable-javascript</PackageTags>
<RepositoryUrl>https://github.com/CSBiology/FsSpreadsheet</RepositoryUrl>
<RepositoryType>git</RepositoryType>
</PropertyGroup>

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Authors>Kevin Frey, Heinrich Lukas Weil, Oliver Maus, Kevin Schneider, Timo Mühlhaus</Authors>
<Description>Excel IO Extensions for the FsSpreadsheet Datamodel in js environments using exceljs.</Description>
<Summary>Spreadsheet creation and manipulation in FSharp</Summary>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageIcon>logo.png</PackageIcon>
<PackageTags>F# FSharp spreadsheet Excel xlsx datascience fable fable-library fable-javascript</PackageTags>
<RepositoryUrl>https://github.com/CSBiology/FsSpreadsheet</RepositoryUrl>
<RepositoryType>git</RepositoryType>
</PropertyGroup>

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<None Include="..\..\docs\img\logo.png" Link="logo.png">
<PackagePath>\</PackagePath>
<Pack>true</Pack>
</None>
<Compile Include="Table.fs" />
<Compile Include="Worksheet.fs" />
<Compile Include="Workbook.fs" />
<Compile Include="Xlsx.fs" />
<Compile Include="FsExtensions.fs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Fable.Exceljs" Version="1.6.0" />
<PackageReference Include="Fable.Promise" Version="3.2.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\FsSpreadsheet\FsSpreadsheet.fsproj" />
</ItemGroup>

<ItemGroup>
<Content Include="*.fsproj; **\*.fs; **\*.fsi" PackagePath="fable\" />
</ItemGroup>

<ItemGroup />

<PropertyGroup>
<NpmDependencies>
<NpmPackage Name="@nfdi4plants/exceljs" Version="gte 0.1.0 lt 1.0.0" ResolutionStrategy="Max" />
</NpmDependencies>
</PropertyGroup>

</Project>
</None>
<Compile Include="Cell.fs" />
<Compile Include="Table.fs" />
<Compile Include="Worksheet.fs" />
<Compile Include="Workbook.fs" />
<Compile Include="Xlsx.fs" />
<Compile Include="FsExtensions.fs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Fable.Exceljs" Version="1.6.0" />
<PackageReference Include="Fable.Promise" Version="3.2.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\FsSpreadsheet\FsSpreadsheet.fsproj" />
</ItemGroup>

<ItemGroup />

<ItemGroup />

<PropertyGroup>
<NpmDependencies>
<NpmPackage Name="@nfdi4plants/exceljs" Version="gte 0.1.0 lt 1.0.0" ResolutionStrategy="Max" />
</NpmDependencies>
</PropertyGroup>

</Project>
29 changes: 9 additions & 20 deletions src/FsSpreadsheet.Exceljs/Table.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module JsTable =
[<Emit("console.log($0)")>]
let private log (obj:obj) = jsNative

let fromFsTable (fscellcollection: FsCellsCollection) (fsTable: FsTable) : Table =
let writeFromFsTable (fscellcollection: FsCellsCollection) (fsTable: FsTable) : Table =
let fsColumns = fsTable.GetColumns fscellcollection
let columns =
if fsTable.ShowHeaderRow then
Expand All @@ -24,36 +24,25 @@ module JsTable =
[| for col in fsColumns do
let cells =
if fsTable.ShowHeaderRow then col.Cells |> Seq.tail else col.Cells
yield! cells |> Seq.mapi (fun i c ->
let rowValue =
match c.DataType with
| Boolean -> c.ValueAsBool() |> box
| Number -> c.ValueAsFloat() |> box
| Date -> c.ValueAsDateTime() |> box
| String -> c.Value |> box
| anyElse ->
let msg = sprintf "ValueType '%A' is not fully implemented in FsSpreadsheet and is handled as string input." anyElse
#if FABLE_COMPILER_JAVASCRIPT
log msg
#else
printfn "%s" msg
#endif
c.Value |> box
i+1, rowValue
yield! cells |> Seq.map (fun c ->
let rowValue = JsCell.writeFromFsCell c |> Option.get
c.Address.RowNumber, (c.Address.ColumnNumber, rowValue)
)
|]
|> Array.groupBy fst
|> Array.sortBy fst
|> Array.map (fun (_,arr) ->
arr |> Array.map snd
let m = arr |> Array.map snd |> Map
let row = [|fsTable.RangeAddress.FirstAddress.ColumnNumber .. fsTable.RangeAddress.FirstAddress.ColumnNumber + (columns.Length-1)|]
let row = row |> Array.map (fun i -> m.TryFind i |> box)
row
)
let defaultStyle = {|
theme = "TableStyleMedium7"
showRowStripes = true
|}
Table(fsTable.Name,fsTable.RangeAddress.Range,columns,rows,fsTable.Name,headerRow = fsTable.ShowHeaderRow, style = defaultStyle)

let fromJsTable(table:ITableRef) =
let readToFsTable(table:ITableRef) =
let table = table.table.Value
let tableRef = table.tableRef |> FsRangeAddress
let tableName = if isNull table.displayName then table.name else table.displayName
Expand Down
16 changes: 8 additions & 8 deletions src/FsSpreadsheet.Exceljs/Workbook.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ module JsWorkbook =
[<Emit("console.log($0)")>]
let private log (obj:obj) = jsNative

let toFsWorkbook (jswb: Workbook) =
let fswb = new FsWorkbook()
for jsws in jswb.worksheets do
JsWorksheet.addJsWorksheet fswb jsws
fswb

let fromFsWorkbook (fswb: FsWorkbook) =
let writeFromFsWorkbook (fswb: FsWorkbook) =
let jswb = ExcelJs.Excel.Workbook()
jswb?_themes <- Aux.theme1
for fsws in fswb.GetWorksheets() do
JsWorksheet.addFsWorksheet jswb fsws
JsWorksheet.writeFromFsWorksheet jswb fsws
jswb

let readToFsWorkbook (jswb: Workbook) =
let fswb = new FsWorkbook()
for jsws in jswb.worksheets do
JsWorksheet.readToFsWorksheet fswb jsws
fswb
Loading

0 comments on commit 56d533f

Please sign in to comment.