Skip to content

Commit

Permalink
Merge pull request #70 from fslaborg/issue_69
Browse files Browse the repository at this point in the history
Issue 69 (nice)
  • Loading branch information
HLWeil authored Oct 13, 2023
2 parents e0b42c7 + 858d6d8 commit eedf32f
Show file tree
Hide file tree
Showing 16 changed files with 97 additions and 39 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ pkg/
tmp/
.fsdocs/
/tests/FsSpreadsheet.JsNativeTests/fable/**/*.js
/tests/FsSpreadsheet.ExcelIO.Tests/TestFiles/WRITE_*.xlsx
/tests/JS/TestFiles/WRITE_*.xlsx
/js
/tests/FsSpreadsheet.Tests/js
/tests/JS/fable
Expand Down
1 change: 1 addition & 0 deletions build/TestTasks.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module RunTests =
let runTestsJs = BuildTask.create "runTestsJS" [clean; build] {
run npm "test" ""
run npm "run testexceljs" ""
run npm "run testjs" ""
}

let runTestsDotnet = BuildTask.create "runTestsDotnet" [clean; build] {
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 10 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
"type": "module",
"main": "Xlsx.js",
"scripts": {
"clean-test": "cd tests/FsSpreadsheet.Tests/js & dotnet fable clean --extension .js --yes",
"pretest": "npm run clean-test && dotnet fable tests/FsSpreadsheet.Tests -o tests/FsSpreadsheet.Tests/js",
"pretest": "dotnet fable tests/FsSpreadsheet.Tests --noCache -o tests/FsSpreadsheet.Tests/js",
"test": "mocha tests/FsSpreadsheet.Tests/js",
"clean-testexceljs": "cd tests/FsSpreadsheet.Exceljs.Tests/js & dotnet fable clean --extension .js --yes",
"pretestexceljs": "npm run clean-testexceljs && dotnet fable tests/FsSpreadsheet.Exceljs.Tests -o tests/FsSpreadsheet.Exceljs.Tests/js",
"pretestexceljs": "dotnet fable tests/FsSpreadsheet.Exceljs.Tests --noCache -o tests/FsSpreadsheet.Exceljs.Tests/js",
"testexceljs": "mocha tests/FsSpreadsheet.Exceljs.Tests/js --timeout 20000",
"clean-testjs": "cd tests/JS/FsSpreadsheet.Exceljs & dotnet fable clean --extension .fs.js --yes",
"pretestjs": "npm run clean-testjs && dotnet fable src/FsSpreadsheet.Exceljs -o tests/JS/FsSpreadsheet.Exceljs --extension .fs.js",
"pretestjs": "dotnet fable src/FsSpreadsheet.Exceljs --noCache -o tests/JS/FsSpreadsheet.Exceljs",
"testjs": "mocha tests/JS --timeout 20000",
"prebundle": "mkdir dist & dotnet fable clean --extension .js --yes -o dist",
"bundle": "dotnet fable src/FsSpreadsheet.Exceljs -o dist"
Expand All @@ -22,7 +19,12 @@
"url": "git+https://github.com/CSBiology/FsSpreadsheet.git"
},
"author": "Kevin Frey",
"contributors": [ "Heinrich Lukas Weil", "Oliver Maus", "Kevin Schneider", "Timo Mühlhaus" ],
"contributors": [
"Heinrich Lukas Weil",
"Oliver Maus",
"Kevin Schneider",
"Timo Mühlhaus"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/CSBiology/FsSpreadsheet/issues"
Expand All @@ -32,6 +34,6 @@
"mocha": "^10.2.0"
},
"dependencies": {
"@nfdi4plants/exceljs": "0.2.0"
"@nfdi4plants/exceljs": "^0.3.0"
}
}
1 change: 1 addition & 0 deletions src/FsSpreadsheet.ExcelIO/Table.fs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ module Table =
a.Reference <- area
t.AutoFilter <- a
t.Reference <- area
t.Name <- StringValue(displayName)
t.DisplayName <- StringValue(displayName)
t.TableColumns <- TableColumns.create tableColumns
t
Expand Down
19 changes: 13 additions & 6 deletions src/FsSpreadsheet.Exceljs/Table.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ module JsTable =
let private log (obj:obj) = jsNative

let fromFsTable (fscellcollection: FsCellsCollection) (fsTable: FsTable) : Table =
let fsColumns = fsTable.GetColumns fscellcollection
let columns =
if fsTable.ShowHeaderRow then
[| for headerCell in fsTable.HeadersRow().Cells(fscellcollection) do
yield TableColumn(headerCell.Value) |]
else
[||]
[|
for i in 1 .. Seq.length fsColumns do yield TableColumn(string i)
|]
let rows =
[| for col in fsTable.GetColumns fscellcollection do
let cells = if fsTable.ShowHeaderRow then col.Cells |> Seq.tail else col.Cells
[| 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
Expand All @@ -35,13 +39,16 @@ module JsTable =
printfn "%s" msg
#endif
c.Value |> box
i, rowValue
i+1, rowValue
)
|]
|> Array.groupBy fst
|> Array.sortBy fst
|> Array.map (fun (_,arr) ->
arr |> Array.map snd
)

Table(fsTable.Name,fsTable.RangeAddress.Range,columns,rows,headerRow = fsTable.ShowHeaderRow)
let defaultStyle = {|
theme = "TableStyleMedium7"
showRowStripes = true
|}
Table(fsTable.Name,fsTable.RangeAddress.Range,columns,rows,fsTable.Name,headerRow = fsTable.ShowHeaderRow, style = defaultStyle)
9 changes: 7 additions & 2 deletions src/FsSpreadsheet.Exceljs/Workbook.fs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
namespace FsSpreadsheet.Exceljs


module JsWorkbook =
open FsSpreadsheet
open Fable.ExcelJs
open Fable.Core
open Fable.Core.JsInterop

module private Aux =

let theme1 = {|theme1 = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>""" + """<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme"><a:themeElements><a:clrScheme name="Office"><a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1><a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1><a:dk2><a:srgbClr val="44546A"/></a:dk2><a:lt2><a:srgbClr val="E7E6E6"/></a:lt2><a:accent1><a:srgbClr val="4472C4"/></a:accent1><a:accent2><a:srgbClr val="ED7D31"/></a:accent2><a:accent3><a:srgbClr val="A5A5A5"/></a:accent3><a:accent4><a:srgbClr val="FFC000"/></a:accent4><a:accent5><a:srgbClr val="5B9BD5"/></a:accent5><a:accent6><a:srgbClr val="70AD47"/></a:accent6><a:hlink><a:srgbClr val="0563C1"/></a:hlink><a:folHlink><a:srgbClr val="954F72"/></a:folHlink></a:clrScheme><a:fontScheme name="Office"><a:majorFont><a:latin typeface="Calibri Light" panose="020F0302020204030204"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="游ゴシック Light"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="等线 Light"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Times New Roman"/><a:font script="Hebr" typeface="Times New Roman"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="MoolBoran"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Times New Roman"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/><a:font script="Armn" typeface="Arial"/><a:font script="Bugi" typeface="Leelawadee UI"/><a:font script="Bopo" typeface="Microsoft JhengHei"/><a:font script="Java" typeface="Javanese Text"/><a:font script="Lisu" typeface="Segoe UI"/><a:font script="Mymr" typeface="Myanmar Text"/><a:font script="Nkoo" typeface="Ebrima"/><a:font script="Olck" typeface="Nirmala UI"/><a:font script="Osma" typeface="Ebrima"/><a:font script="Phag" typeface="Phagspa"/><a:font script="Syrn" typeface="Estrangelo Edessa"/><a:font script="Syrj" typeface="Estrangelo Edessa"/><a:font script="Syre" typeface="Estrangelo Edessa"/><a:font script="Sora" typeface="Nirmala UI"/><a:font script="Tale" typeface="Microsoft Tai Le"/><a:font script="Talu" typeface="Microsoft New Tai Lue"/><a:font script="Tfng" typeface="Ebrima"/></a:majorFont><a:minorFont><a:latin typeface="Calibri" panose="020F0502020204030204"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="游ゴシック"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="等线"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Arial"/><a:font script="Hebr" typeface="Arial"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="DaunPenh"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Arial"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/><a:font script="Armn" typeface="Arial"/><a:font script="Bugi" typeface="Leelawadee UI"/><a:font script="Bopo" typeface="Microsoft JhengHei"/><a:font script="Java" typeface="Javanese Text"/><a:font script="Lisu" typeface="Segoe UI"/><a:font script="Mymr" typeface="Myanmar Text"/><a:font script="Nkoo" typeface="Ebrima"/><a:font script="Olck" typeface="Nirmala UI"/><a:font script="Osma" typeface="Ebrima"/><a:font script="Phag" typeface="Phagspa"/><a:font script="Syrn" typeface="Estrangelo Edessa"/><a:font script="Syrj" typeface="Estrangelo Edessa"/><a:font script="Syre" typeface="Estrangelo Edessa"/><a:font script="Sora" typeface="Nirmala UI"/><a:font script="Tale" typeface="Microsoft Tai Le"/><a:font script="Talu" typeface="Microsoft New Tai Lue"/><a:font script="Tfng" typeface="Ebrima"/></a:minorFont></a:fontScheme><a:fmtScheme name="Office"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:lumMod val="110000"/><a:satMod val="105000"/><a:tint val="67000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:lumMod val="105000"/><a:satMod val="103000"/><a:tint val="73000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:lumMod val="105000"/><a:satMod val="109000"/><a:tint val="81000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:satMod val="103000"/><a:lumMod val="102000"/><a:tint val="94000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:satMod val="110000"/><a:lumMod val="100000"/><a:shade val="100000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:lumMod val="99000"/><a:satMod val="120000"/><a:shade val="78000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill></a:fillStyleLst><a:lnStyleLst><a:ln w="6350" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln><a:ln w="12700" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln><a:ln w="19050" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="63000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:solidFill><a:schemeClr val="phClr"><a:tint val="95000"/><a:satMod val="170000"/></a:schemeClr></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="93000"/><a:satMod val="150000"/><a:shade val="98000"/><a:lumMod val="102000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:tint val="98000"/><a:satMod val="130000"/><a:shade val="90000"/><a:lumMod val="103000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="63000"/><a:satMod val="120000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults/><a:extraClrSchemeLst/><a:extLst><a:ext uri="{05A4C25C-085E-4340-85A3-A5531E510DB2}"><thm15:themeFamily xmlns:thm15="http://schemas.microsoft.com/office/thememl/2012/main" name="Office Theme" id="{62F939B6-93AF-4DB8-9C6B-D6C7DFDC589F}" vid="{4A3C46E8-61CC-4603-A589-7422A47A8E4A}"/></a:ext></a:extLst></a:theme>"""|}

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

Expand All @@ -15,8 +19,9 @@ module JsWorkbook =
JsWorksheet.addJsWorksheet fswb jsws
fswb

let toJsWorkbook (fswb: FsWorkbook) =
let fromFsWorkbook (fswb: FsWorkbook) =
let jswb = ExcelJs.Excel.Workbook()
jswb?_themes <- Aux.theme1
for fsws in fswb.GetWorksheets() do
JsWorksheet.addFsWorksheet jswb fsws
jswb
6 changes: 3 additions & 3 deletions src/FsSpreadsheet.Exceljs/Xlsx.fs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ type Xlsx =
}

static member toFile (path: string) (wb:FsWorkbook) : Promise<unit> =
let jswb = JsWorkbook.toJsWorkbook wb
let jswb = JsWorkbook.fromFsWorkbook wb
jswb.xlsx.writeFile(path)

static member toStream (stream: System.IO.Stream) (wb:FsWorkbook) : Promise<unit> =
let jswb = JsWorkbook.toJsWorkbook wb
let jswb = JsWorkbook.fromFsWorkbook wb
jswb.xlsx.write(stream)

static member toBytes (wb:FsWorkbook) : Promise<byte []> =
promise {
let jswb = JsWorkbook.toJsWorkbook wb
let jswb = JsWorkbook.fromFsWorkbook wb
let buffer = jswb.xlsx.writeBuffer()
return !!buffer
}
Expand Down
14 changes: 14 additions & 0 deletions tests/FsSpreadsheet.ExcelIO.Tests/FsWorkbook.fs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ let writeAndReadBytes =
Expect.workSheetEqual (wb.GetWorksheetByName(TestObjects.sheet1Name)) (wb2.GetWorksheetByName(TestObjects.sheet1Name)) "First Worksheet did not match"
Expect.workSheetEqual (wb.GetWorksheetByName(TestObjects.sheet2Name)) (wb2.GetWorksheetByName(TestObjects.sheet2Name)) "Second Worksheet did not match"
)
testCase "WriteToDisc" (fun () ->
let wb = new FsWorkbook()
let ws1 = TestObjects.sheet1()
let table = ws1.Table("My Test Table", FsRangeAddress(FsAddress(1,1),FsAddress(3,3)))
wb.AddWorksheet(ws1)
wb.AddWorksheet(TestObjects.sheet2())
System.IO.Directory.CreateDirectory("./TestFiles") |> ignore
let p = "./TestFiles/WRITE_Roundabout.xlsx"
wb.ToFile(p)
let wb2 = FsWorkbook.fromXlsxFile(p)
Expect.equal (wb.GetWorksheets().Count) (wb2.GetWorksheets().Count) "Worksheet count should be equal"
Expect.workSheetEqual (wb.GetWorksheetByName(TestObjects.sheet1Name)) (wb2.GetWorksheetByName(TestObjects.sheet1Name)) "First Worksheet did not match"
Expect.workSheetEqual (wb.GetWorksheetByName(TestObjects.sheet2Name)) (wb2.GetWorksheetByName(TestObjects.sheet2Name)) "Second Worksheet did not match"
)
]


Expand Down
4 changes: 4 additions & 0 deletions tests/FsSpreadsheet.ExcelIO.Tests/TestFiles/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Files found here follow the following rules:

- Files starting with **WRITE_** are created by tests.
- Other files should not be deleted or opened/saved to avoid corrupting tests.
12 changes: 6 additions & 6 deletions tests/FsSpreadsheet.Exceljs.Tests/Workbook.Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ let tests_toJsWorkbook = testList "toJsWorkbook" [
testCase "empty" <| fun _ ->
let fswb = new FsWorkbook()
Expect.passWithMsg "Create fswb"
let jswb = JsWorkbook.toJsWorkbook fswb
let jswb = JsWorkbook.fromFsWorkbook fswb
Expect.passWithMsg "Convert to jswb"
let fswsList = fswb.GetWorksheets()
let jswsList = jswb.worksheets
Expand All @@ -141,7 +141,7 @@ let tests_toJsWorkbook = testList "toJsWorkbook" [
let fswb = new FsWorkbook()
let _ = fswb.InitWorksheet("My Awesome Worksheet")
Expect.passWithMsg "Create fswb"
let jswb = JsWorkbook.toJsWorkbook fswb
let jswb = JsWorkbook.fromFsWorkbook fswb
Expect.passWithMsg "Convert to jswb"
let fswsList = fswb.GetWorksheets()
let jswsList = jswb.worksheets
Expand All @@ -154,7 +154,7 @@ let tests_toJsWorkbook = testList "toJsWorkbook" [
let _ = fswb.InitWorksheet("My cool Worksheet")
let _ = fswb.InitWorksheet("My wow Worksheet")
Expect.passWithMsg "Create fswb"
let jswb = JsWorkbook.toJsWorkbook fswb
let jswb = JsWorkbook.fromFsWorkbook fswb
Expect.passWithMsg "Convert to jswb"
let fswsList = fswb.GetWorksheets()
let jswsList = jswb.worksheets
Expand All @@ -171,7 +171,7 @@ let tests_toJsWorkbook = testList "toJsWorkbook" [
let t = FsTable("My_New_Table", FsRangeAddress("B1:C1"))
let _ = fsws.AddTable(t)
Expect.passWithMsg "Create jswb"
let jswb = JsWorkbook.toJsWorkbook fswb
let jswb = JsWorkbook.fromFsWorkbook fswb
Expect.passWithMsg "Convert to fswb"
let jsws = jswb.worksheets.[0]
Expect.equal jsws.name "My Awesome Worksheet" "ws name"
Expand All @@ -198,7 +198,7 @@ let tests_toJsWorkbook = testList "toJsWorkbook" [
let t = FsTable("My_New_Table", FsRangeAddress("B1:D3"))
let _ = fsws.AddTable(t)
Expect.passWithMsg "Create jswb"
let jswb = JsWorkbook.toJsWorkbook fswb
let jswb = JsWorkbook.fromFsWorkbook fswb
Expect.passWithMsg "Convert to fswb"
let jsws = jswb.worksheets.[0]
Expect.equal jsws.name "My Awesome Worksheet" "ws name"
Expand Down Expand Up @@ -227,7 +227,7 @@ let tests_toJsWorkbook = testList "toJsWorkbook" [
let _ = fsws.AddTable(t)
fsws.RescanRows()
Expect.passWithMsg "Create jswb"
let jswb = JsWorkbook.toJsWorkbook fswb
let jswb = JsWorkbook.fromFsWorkbook fswb
let jstable = jswb.worksheets.[0].getTables().[0].table.Value
let row0 = jstable.rows.[0]
let row1 = jstable.rows.[1]
Expand Down
Loading

0 comments on commit eedf32f

Please sign in to comment.