Skip to content

Commit

Permalink
Merge pull request #34 from CSBiology/fable
Browse files Browse the repository at this point in the history
Increase fable javascript code quality
  • Loading branch information
HLWeil authored Jul 18, 2023
2 parents 8c8e720 + 70df6e6 commit 4da5e50
Show file tree
Hide file tree
Showing 24 changed files with 192 additions and 234 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "Spreadsheet creation and manipulation in FSharp",
"type": "module",
"scripts": {
"fable-js": "dotnet fable ./src/FsSpreadsheet -o ./js",
"pretest": "dotnet fable tests/FsSpreadsheet.Tests -o tests/FsSpreadsheet.JsNativeTests/fable",
"test": "mocha tests/FsSpreadsheet.JsNativeTests/fable",
"posttest": "mocha tests/FsSpreadsheet.JsNativeTests"
Expand Down
2 changes: 1 addition & 1 deletion src/FsSpreadsheet.ExcelIO/FsExtensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ module FsExtensions =
member self.ToXlsxTable(cells : FsCellsCollection) =

let columns =
self.FieldNames(cells)
self.GetFieldNames(cells)
|> Seq.map (fun kv ->
Table.TableColumn.create (1 + kv.Value.Index |> uint) kv.Value.Name
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace FsSpreadsheet
namespace FsSpreadsheet.Interactive

open FsSpreadsheet

/// A FsSparseMatrix
type FsSparseMatrix<'T>(defaultEmptyValue: 'T,sparseValues : 'T array, sparseRowOffsets : int array, ncols:int, columnValues: int array) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
</ItemGroup>

<ItemGroup>
<Compile Include="FsSparseMatrix.fs" />
<Compile Include="Formatters.fs" />
<Compile Include="Extension.fs" />
<None Include="..\..\docs\img\logo.png" Pack="true" PackagePath="\" />
Expand Down
18 changes: 6 additions & 12 deletions src/FsSpreadsheet/Cells/FsCell.fs
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,23 @@ type DataType =
/// <summary>
/// Creates an FsCell of `DataType` dataType, with value of type `string`, and `FsAddress` address.
/// </summary>
type FsCell (value : IConvertible, dataType : DataType, address : FsAddress) =
type FsCell (value : IConvertible, ?dataType : DataType, ?address : FsAddress) =

// TODO: Maybe save as IConvertible
let mutable _cellValue = string value
let mutable _dataType = dataType
let mutable _dataType = dataType |> Option.defaultValue DataType.String
let mutable _comment = ""
let mutable _hyperlink = ""
let mutable _richText = ""
let mutable _formulaA1 = ""
let mutable _formulaR1C1 = ""

let mutable _rowIndex : int = address.RowNumber
let mutable _columnIndex : int = address.ColumnNumber
let mutable _rowIndex : int = address |> Option.map (fun a -> a.RowNumber) |> Option.defaultValue 0
let mutable _columnIndex : int = address |> Option.map (fun a -> a.ColumnNumber) |> Option.defaultValue 0


// ------------------------
// ALTERNATIVE CONSTRUCTORS
// ------------------------

new (value : IConvertible) = FsCell (string value, DataType.String, FsAddress(0,0))

///// Creates an empty FsCell, set at row 1, column 1 (1-based).
//new () = FsCell ("", DataType.Empty, FsAddress(0,0))
/// Creates an empty FsCell, set at row 0, column 0 (1-based).
static member empty () = FsCell ("", DataType.Empty, FsAddress(0,0))

///// Creates an FsCell of `DataType` `Number`, with the given value, set at row 1, column 1 (1-based).
//new (value : int) = FsCell (string value, DataType.Number, FsAddress(0,0))
Expand Down
22 changes: 13 additions & 9 deletions src/FsSpreadsheet/FsColumn.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,32 @@
open System.Collections.Generic
open System.Collections


open Fable.Core
// Type based on the type XLRow used in ClosedXml
/// <summary>
/// Creates an FsColumn from the given FsRangeAddress, consisting of FsCells within a given FsCellsCollection, and a styleValue.
/// </summary>
/// <remarks>The FsCellsCollection must only cover 1 column!</remarks>
/// <exception cref="System.Exception">if given FsCellsCollection has more than 1 column.</exception>
[<AttachMembers>]
type FsColumn (rangeAddress : FsRangeAddress, cells : FsCellsCollection)=

inherit FsRangeBase(rangeAddress, null)
inherit FsRangeBase(rangeAddress)

let cells = cells

new() = FsColumn (FsRangeAddress(FsAddress(0,0),FsAddress(0,0)),FsCellsCollection())
// ----------
// Creation
// ----------

/// Creates an empty FsColumn, ranging from row 0, column 0 to row 0, column (1-based).
static member empty() = FsColumn (FsRangeAddress(FsAddress(0,0),FsAddress(0,0)),FsCellsCollection())

/// <summary>
/// Create an FsColumn from a given FsCellsCollection and an columnColumn.
/// </summary>
/// <remarks>The appropriate range of the cells (i.e. minimum colIndex and maximum colIndex) is derived from the FsCells with the matching rowIndex.</remarks>
new(index, (cells : FsCellsCollection)) =
static member createAt(index : int32, (cells : FsCellsCollection)) =
let getIndexBy (f : (FsCell -> int) -> seq<FsCell> -> FsCell) =
match cells.GetCellsInColumn index |> Seq.length with
| 0 -> 1
Expand All @@ -35,8 +41,6 @@ type FsColumn (rangeAddress : FsRangeAddress, cells : FsCellsCollection)=
let maxRowIndex = getIndexBy Seq.maxBy
FsColumn (FsRangeAddress(FsAddress(minRowIndex, index),FsAddress(maxRowIndex, index)), cells)

new (columnRange : FsRangeColumn, cells : FsCellsCollection) = FsColumn(columnRange.RangeAddress,cells)

interface IEnumerable<FsCell> with
member this.GetEnumerator() : System.Collections.Generic.IEnumerator<FsCell> = this.Cells.GetEnumerator()

Expand Down Expand Up @@ -100,9 +104,9 @@ type FsColumn (rangeAddress : FsRangeAddress, cells : FsCellsCollection)=
static member item rowIndex (column : FsColumn) =
column.Item(rowIndex)

/// <summary>
/// Inserts the value at columnIndex as an FsCell. If there is an FsCell at the position, this FsCells and all the ones right to it are shifted to the right.
/// </summary>
///// <summary>
///// Inserts the value at columnIndex as an FsCell. If there is an FsCell at the position, this FsCells and all the ones /right /to it are shifted to the right.
///// </summary>
//member this.InsertValueAt(colIndex, (value : 'a)) =
// let cell = FsCell(value)
// cells.Add(int32 this.Index, int32 colIndex, cell)
Expand Down
19 changes: 12 additions & 7 deletions src/FsSpreadsheet/FsRow.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,31 @@
open System.Collections.Generic
open System.Collections


open Fable.Core
// Type based on the type XLRow used in ClosedXml
/// <summary>
/// Creates an FsRow from the given FsRangeAddress, consisting of FsCells within a given FsCellsCollection, and a styleValue.
/// </summary>
/// <remarks>The FsCellsCollection must only cover 1 row!</remarks>
/// <exception cref="System.Exception">if given FsCellsCollection has more than 1 row.</exception>
type FsRow (rangeAddress : FsRangeAddress, cells : FsCellsCollection, styleValue)=
[<AttachMembers>]
type FsRow (rangeAddress : FsRangeAddress, cells : FsCellsCollection)=

inherit FsRangeBase(rangeAddress, styleValue)
inherit FsRangeBase(rangeAddress)

let cells = cells

new() = FsRow (FsRangeAddress(FsAddress(0,0),FsAddress(0,0)),FsCellsCollection(),null)
// ----------
// Creation
// ----------

static member empty() = FsRow (FsRangeAddress(FsAddress(0,0),FsAddress(0,0)),FsCellsCollection())

/// <summary>
/// Create an FsRow from a given FsCellsCollection and an rowIndex.
/// </summary>
/// <remarks>The appropriate range of the cells (i.e. minimum colIndex and maximum colIndex) is derived from the FsCells with the matching rowIndex.</remarks>
new(index, (cells : FsCellsCollection)) =
static member createAt(index, (cells : FsCellsCollection)) =
let getIndexBy (f : (FsCell -> int) -> seq<FsCell> -> FsCell) =
match cells.GetCellsInRow index |> Seq.length with
| 0 -> 1
Expand All @@ -33,7 +38,7 @@ type FsRow (rangeAddress : FsRangeAddress, cells : FsCellsCollection, styleValue
).Address.ColumnNumber
let minColIndex = getIndexBy Seq.minBy
let maxColIndex = getIndexBy Seq.maxBy
FsRow (FsRangeAddress(FsAddress(index, minColIndex),FsAddress(index, maxColIndex)), cells, null)
FsRow (FsRangeAddress(FsAddress(index, minColIndex),FsAddress(index, maxColIndex)), cells)

interface IEnumerable<FsCell> with
member this.GetEnumerator() : System.Collections.Generic.IEnumerator<FsCell> = this.Cells.GetEnumerator()
Expand Down Expand Up @@ -71,7 +76,7 @@ type FsRow (rangeAddress : FsRangeAddress, cells : FsCellsCollection, styleValue
let cells = self.Cells |> Seq.map (fun c -> c.Copy())
let fcc = FsCellsCollection()
fcc.Add cells
FsRow(ra, fcc, null)
FsRow(ra, fcc)

/// <summary>
/// Returns a deep copy of a given FsRow.
Expand Down
5 changes: 4 additions & 1 deletion src/FsSpreadsheet/FsSpreadsheet.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="FsSparseMatrix.fs" />
<Compile Include="FsAddress.fs" />
<Compile Include="Cells\FsCell.fs" />
<Compile Include="Cells\FsCellsCollection.fs" />
Expand Down Expand Up @@ -52,4 +51,8 @@
<Content Include="*.fsproj; **\*.fs; **\*.fsi" PackagePath="fable\" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Fable.Core" Version="4.0.0" />
</ItemGroup>

</Project>
58 changes: 37 additions & 21 deletions src/FsSpreadsheet/FsWorkbook.fs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
namespace FsSpreadsheet


open Fable.Core
/// <summary>
/// Creates an empty FsWorkbook.
/// </summary>
[<AttachMembers>]
type FsWorkbook() =

let mutable _worksheets = []
Expand Down Expand Up @@ -37,17 +39,17 @@ type FsWorkbook() =
workbook.Copy()

/// <summary>
/// Adds an empty FsWorksheet with given name to the FsWorkbook.
/// Creates an empty FsWorksheet with given name and adds it to the FsWorkbook.
/// </summary>
member self.AddWorksheet(name : string) =
member self.InitWorksheet(name : string) =
let sheet = FsWorksheet name
_worksheets <- List.append _worksheets [sheet]

/// <summary>
/// Adds an empty FsWorksheet with given name to an FsWorkbook.
/// Creates an empty FsWorksheet with given name and adds it to the FsWorkbook.
/// </summary>
static member addWorksheetWithName (name : string) (workbook : FsWorkbook) =
workbook.AddWorksheet name
static member initWorksheet (name : string) (workbook : FsWorkbook) =
workbook.InitWorksheet name
workbook


Expand Down Expand Up @@ -93,6 +95,34 @@ type FsWorkbook() =
static member getWorksheets (workbook : FsWorkbook) =
workbook.GetWorksheets()

/// <summary>
/// Returns the FsWorksheet with the given 1 based index if it exists. Else returns None.
/// </summary>
member self.TryGetWorksheetAt(index : int) =
_worksheets |> List.tryItem (index - 1)

/// <summary>
/// Returns the FsWorksheet with the given 1 based index if it exists in a given FsWorkbook. Else returns None.
/// </summary>
static member tryGetWorksheetAt (index : int) (workbook : FsWorkbook) =
workbook.TryGetWorksheetAt index

/// <summary>
/// Returns the FsWorksheet with the given 1 based index.
/// </summary>
/// <exception cref="System.Exception">if FsWorksheet with at position is not present in the FsWorkkbook.</exception>
member self.GetWorksheetAt(index : int) =
match self.TryGetWorksheetAt index with
| Some w -> w
| None -> failwith $"FsWorksheet at position {index} is not present in the FsWorkbook."

/// <summary>
/// Returns the FsWorksheet with the given the given 1 based indexk.
/// </summary>
/// <exception cref="System.Exception">if FsWorksheet with at position is not present in the FsWorkkbook.</exception>
static member getWorksheetAt (index : int) (workbook : FsWorkbook) =
workbook.GetWorksheetAt index

/// <summary>
/// Returns the FsWorksheet with the given name if it exists in the FsWorkbook. Else returns None.
/// </summary>
Expand Down Expand Up @@ -134,24 +164,10 @@ type FsWorkbook() =
/// <summary>
/// Removes an FsWorksheet with given name from an FsWorkbook.
/// </summary>
static member removeWorksheetByName (name : string) (workbook : FsWorkbook) =
static member removeWorksheet (name : string) (workbook : FsWorkbook) =
workbook.RemoveWorksheet name
workbook

/// <summary>
/// Removes a given FsWorksheet.
/// </summary>
/// <exception cref="System.Exception">if FsWorksheet with given name is not present in the FsWorkkbook.</exception>
member self.RemoveWorksheet(sheet : FsWorksheet) =
self.RemoveWorksheet(sheet.Name)

/// <summary>
/// Removes a given FsWorksheet from an FsWorkbook.
/// </summary>
static member removeWorksheet (sheet : FsWorksheet) (workbook : FsWorkbook) =
workbook.RemoveWorksheet sheet
workbook

/// <summary>
/// Returns all FsTables from the FsWorkbook.
/// </summary>
Expand Down
38 changes: 15 additions & 23 deletions src/FsSpreadsheet/FsWorksheet.fs
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
namespace FsSpreadsheet

open Fable.Core

// Type based on the type XLWorksheet used in ClosedXml
/// <summary>
/// Creates an FsWorksheet with the given name, FsRows, FsTables, and FsCellsCollection.
/// </summary>
type FsWorksheet (name, fsRows, fsTables, fsCellsCollection) =
[<AttachMembers>]
type FsWorksheet (name, ?fsRows, ?fsTables, ?fsCellsCollection) =

let mutable _name = name

let mutable _rows : FsRow list = fsRows

let mutable _tables : FsTable list = fsTables
let mutable _rows : FsRow list = fsRows |> Option.defaultValue []

let mutable _cells : FsCellsCollection = fsCellsCollection
let mutable _tables : FsTable list = fsTables |> Option.defaultValue []

/// <summary>
/// Creates an empty FsWorksheet.
/// </summary>
new () =
FsWorksheet("")
let mutable _cells : FsCellsCollection = fsCellsCollection |> Option.defaultValue (FsCellsCollection())

/// <summary>
/// Creates an empty FsWorksheet with the given name.
/// </summary>
new (name) =
static member init (name) =
FsWorksheet(name, [], [], FsCellsCollection())

// TO DO: finish
Expand Down Expand Up @@ -131,14 +128,14 @@ type FsWorksheet (name, fsRows, fsTables, fsCellsCollection) =
| Some row ->
row
| None ->
let row = FsRow(rowIndex,self.CellCollection)
let row = FsRow.createAt(rowIndex,self.CellCollection)
_rows <- List.append _rows [row]
row

/// <summary>
/// Returns the FsRow at the given FsRangeAddress. If it does not exist, it is created and appended first.
/// </summary>
member self.Row(rangeAddress : FsRangeAddress) =
member self.RowWithRange(rangeAddress : FsRangeAddress) =
if rangeAddress.FirstAddress.RowNumber <> rangeAddress.LastAddress.RowNumber then
failwithf "Row may not have a range address spanning over different row indices"
self.Row(rangeAddress.FirstAddress.RowNumber).RangeAddress <- rangeAddress
Expand Down Expand Up @@ -357,7 +354,7 @@ type FsWorksheet (name, fsRows, fsTables, fsCellsCollection) =
| Some row ->
row.RangeAddress <- newRange
| None ->
self.Row(newRange)
self.RowWithRange(newRange)
)


Expand All @@ -369,12 +366,12 @@ type FsWorksheet (name, fsRows, fsTables, fsCellsCollection) =
/// <summary>
/// Returns the FsColumn at the given index. If it does not exist, it is created and appended first.
/// </summary>
member self.Column(columnIndex : int32) = FsColumn(columnIndex,self.CellCollection)
member self.Column(columnIndex : int32) = FsColumn.createAt(columnIndex,self.CellCollection)

/// <summary>
/// Returns the FsColumn at the given FsRangeAddress. If it does not exist, it is created and appended first.
/// </summary>
member self.Column(rangeAddress : FsRangeAddress) =
member self.ColumnWithRange(rangeAddress : FsRangeAddress) =
if rangeAddress.FirstAddress.ColumnNumber <> rangeAddress.LastAddress.ColumnNumber then
failwithf "Column may not have a range address spanning over different column indices"
self.Column(rangeAddress.FirstAddress.ColumnNumber).RangeAddress <- rangeAddress
Expand Down Expand Up @@ -408,20 +405,15 @@ type FsWorksheet (name, fsRows, fsTables, fsCellsCollection) =
/// Returns the FsTable with the given tableName, rangeAddress, and showHeaderRow parameters. If it does not exist yet, it gets created and appended first.
/// </summary>
// TO DO: Ask HLW: Is this really a good name for the method?
member self.Table(tableName,rangeAddress,showHeaderRow) =
member self.Table(tableName,rangeAddress,?showHeaderRow : bool) =
let showHeaderRow = defaultArg showHeaderRow true
match _tables |> List.tryFind (fun table -> table.Name = name) with
| Some table ->
table
| None ->
let table = FsTable(tableName,rangeAddress,showHeaderRow)
_tables <- List.append _tables [table]
table

/// <summary>
/// Returns the FsTable with the given tableName and rangeAddress parameters. If it does not exist yet, it gets created first. ShowHeaderRow is true by default.
/// </summary>
member self.Table(tableName,rangeAddress) =
self.Table(tableName,rangeAddress,true)

/// <summary>
/// Returns the FsTable of the given name from an FsWorksheet if it exists. Else returns None.
Expand Down
Loading

0 comments on commit 4da5e50

Please sign in to comment.