diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 4b3f5945..de1fe6b2 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -9,7 +9,7 @@ ] }, "fable": { - "version": "4.1.3", + "version": "4.13.0", "commands": [ "fable" ] diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index eb05c93e..a6fab499 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -7,48 +7,63 @@ on: branches: [ main ] jobs: - build-and-test-linux: + test: - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 + + # SETUP .NET - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: 6.x.x - name: Restore fable run: dotnet tool restore + + # SETUP NODE - name: Setup Node.js environment uses: actions/setup-node@v3 with: node-version: 16 - name: install node modules - run: npm install - - name: make script executable - run: chmod u+x build.sh - - name: Build and test dotnet working-directory: ./ - run: ./build.sh runtests - - build-and-test-windows: - - runs-on: windows-latest + run: npm install --ignore-scripts - steps: - - uses: actions/checkout@v3 - - name: Setup .NET - uses: actions/setup-dotnet@v3 - with: - dotnet-version: 6.x.x - - name: Restore fable - run: dotnet tool restore - - name: Setup Node.js environment - uses: actions/setup-node@v3 + # SETUP PYTHON + - name: Setup Python + uses: actions/setup-python@v5 with: - node-version: 16 - - name: install node modules - run: npm install - - name: Build and test dotnet + python-version: '3.11' + - name: Setup Virtual Environment + run: python -m venv .venv + - name: Setup Poetry Windows + if: matrix.os == 'windows-latest' + run: | + .\.venv\Scripts\python.exe -m pip install -U pip setuptools + .\.venv\Scripts\python.exe -m pip install poetry + .\.venv\Scripts\python.exe -m poetry install --no-root + - name: Setup Poetry Unix + if: matrix.os == 'ubuntu-latest' + run: | + ./.venv/bin/python -m pip install -U pip setuptools + ./.venv/bin/python -m pip install poetry + ./.venv/bin/python -m poetry install --no-root + + # BUILD + - name: make script executable + if: matrix.os == 'ubuntu-latest' + run: chmod u+x build.sh + - name: Test (Unix) + if: matrix.os == 'ubuntu-latest' working-directory: ./ - run: ./build.cmd runtests \ No newline at end of file + run: ./build.sh runtests + - name: Test (Windows) + if: matrix.os == 'windows-latest' + run: .\build.cmd runtests \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3c06283b..2f0773c2 100644 --- a/.gitignore +++ b/.gitignore @@ -355,11 +355,15 @@ tmp/ output/ .fsdocs/ /tests/FsSpreadsheet.JsNativeTests/fable/**/*.js -**/TestFiles/WRITE_*.xlsx +/tests/FsSpreadsheet.Net.Tests/TestFiles/WRITE_*.xlsx +/tests/JS/TestFiles/WRITE_*.xlsx +/tests/TestUtils/TestFiles/TestWorkbook_FsSpreadsheet_WRITE.*.xlsx /js +**/py/** +/.venv /tests/FsSpreadsheet.Tests/js /tests/JS/fable -/tests/JS/FsSpreadsheet.Exceljs -/tests/FsSpreadsheet.Exceljs.Tests/js +/tests/JS/FsSpreadsheet.Js +/tests/FsSpreadsheet.Js.Tests/js /dist /tests/TestUtils/TestFiles/Scripts/fable diff --git a/FsSpreadsheet.sln b/FsSpreadsheet.sln index 385997eb..1d677f7d 100644 --- a/FsSpreadsheet.sln +++ b/FsSpreadsheet.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 15.0.26124.0 Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet", "src\FsSpreadsheet\FsSpreadsheet.fsproj", "{601DB071-B467-4237-9403-E63616038B61}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.ExcelIO", "src\FsSpreadsheet.ExcelIO\FsSpreadsheet.ExcelIO.fsproj", "{1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}" -EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Tests", "tests\FsSpreadsheet.Tests\FsSpreadsheet.Tests.fsproj", "{CBA2E524-B861-44FE-A0B0-668E57FF2A24}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{276B4810-B0CB-4FDF-9CED-49B3DD59B19F}" @@ -20,6 +18,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{276B package.json = package.json playground.fsx = playground.fsx .github\workflows\publish-github-pages.yml = .github\workflows\publish-github-pages.yml + pyproject.toml = pyproject.toml README.md = README.md RELEASE_NOTES.md = RELEASE_NOTES.md EndProjectSection @@ -28,8 +27,6 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.CsvIO", "src\ EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Build", "build\Build.fsproj", "{544DA4BF-E0DB-4222-B5DB-E9A7B9E2A5DD}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.ExcelIO.Tests", "tests\FsSpreadsheet.ExcelIO.Tests\FsSpreadsheet.ExcelIO.Tests.fsproj", "{C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}" -EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Interactive", "src\FsSpreadsheet.Interactive\FsSpreadsheet.Interactive.fsproj", "{5F8EBA76-7B6B-4BAF-9426-F17B14FA5C4C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1CF1274C-DE28-4446-9B4E-5884E797B87B}" @@ -38,10 +35,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{F77AD108 EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Interactive.Tests", "tests\FsSpreadsheet.Interactive.Tests\FsSpreadsheet.Interactive.Tests.fsproj", "{7AC6357C-BDA0-40AE-955E-953C4BFF5BB0}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Exceljs", "src\FsSpreadsheet.Exceljs\FsSpreadsheet.Exceljs.fsproj", "{E72A14FF-5026-463B-B0FA-2DA104D67B0C}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Exceljs.Tests", "tests\FsSpreadsheet.Exceljs.Tests\FsSpreadsheet.Exceljs.Tests.fsproj", "{96E12F19-B25A-415E-B965-F9DE8D713C67}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JS", "JS", "{ADCF7D08-F2EE-4DFD-A96A-7E0134A1546F}" ProjectSection(SolutionItems) = preProject tests\JS\Exceljs.js = tests\JS\Exceljs.js @@ -49,7 +42,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JS", "JS", "{ADCF7D08-F2EE- EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TestUtils", "tests\TestUtils\TestUtils.fsproj", "{60678E53-EDC4-4ADE-A9EE-B194BDC76B37}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Speedtest", "tests\Speedtest\Speedtest.fsproj", "{6DAD5C65-64CA-4ED4-B609-2D068F021024}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Speedtest", "tests\Speedtest\Speedtest.fsproj", "{6DAD5C65-64CA-4ED4-B609-2D068F021024}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Js", "src\FsSpreadsheet.Js\FsSpreadsheet.Js.fsproj", "{ADD70570-8B1B-43C6-88DD-DE01612F19B6}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Net", "src\FsSpreadsheet.Net\FsSpreadsheet.Net.fsproj", "{6262163F-7E77-4BBD-B5FF-73EDE1AB203F}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Py", "src\FsSpreadsheet.Py\FsSpreadsheet.Py.fsproj", "{BCA94498-0C74-4EBF-94BB-3A90A6996204}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Js.Tests", "tests\FsSpreadsheet.Js.Tests\FsSpreadsheet.Js.Tests.fsproj", "{2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Py.Tests", "tests\FsSpreadsheet.Py.Tests\FsSpreadsheet.Py.Tests.fsproj", "{248FFB22-4BDD-40FA-A625-D957C1989A1B}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsSpreadsheet.Net.Tests", "tests\FsSpreadsheet.Net.Tests\FsSpreadsheet.Net.Tests.fsproj", "{935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -73,18 +78,6 @@ Global {601DB071-B467-4237-9403-E63616038B61}.Release|x64.Build.0 = Release|Any CPU {601DB071-B467-4237-9403-E63616038B61}.Release|x86.ActiveCfg = Release|Any CPU {601DB071-B467-4237-9403-E63616038B61}.Release|x86.Build.0 = Release|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Debug|x64.ActiveCfg = Debug|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Debug|x64.Build.0 = Debug|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Debug|x86.ActiveCfg = Debug|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Debug|x86.Build.0 = Debug|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Release|Any CPU.Build.0 = Release|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Release|x64.ActiveCfg = Release|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Release|x64.Build.0 = Release|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Release|x86.ActiveCfg = Release|Any CPU - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5}.Release|x86.Build.0 = Release|Any CPU {CBA2E524-B861-44FE-A0B0-668E57FF2A24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CBA2E524-B861-44FE-A0B0-668E57FF2A24}.Debug|Any CPU.Build.0 = Debug|Any CPU {CBA2E524-B861-44FE-A0B0-668E57FF2A24}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -121,18 +114,6 @@ Global {544DA4BF-E0DB-4222-B5DB-E9A7B9E2A5DD}.Release|x64.Build.0 = Release|Any CPU {544DA4BF-E0DB-4222-B5DB-E9A7B9E2A5DD}.Release|x86.ActiveCfg = Release|Any CPU {544DA4BF-E0DB-4222-B5DB-E9A7B9E2A5DD}.Release|x86.Build.0 = Release|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Debug|x64.ActiveCfg = Debug|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Debug|x64.Build.0 = Debug|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Debug|x86.ActiveCfg = Debug|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Debug|x86.Build.0 = Debug|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Release|Any CPU.Build.0 = Release|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Release|x64.ActiveCfg = Release|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Release|x64.Build.0 = Release|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Release|x86.ActiveCfg = Release|Any CPU - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32}.Release|x86.Build.0 = Release|Any CPU {5F8EBA76-7B6B-4BAF-9426-F17B14FA5C4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5F8EBA76-7B6B-4BAF-9426-F17B14FA5C4C}.Debug|Any CPU.Build.0 = Debug|Any CPU {5F8EBA76-7B6B-4BAF-9426-F17B14FA5C4C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -157,30 +138,6 @@ Global {7AC6357C-BDA0-40AE-955E-953C4BFF5BB0}.Release|x64.Build.0 = Release|Any CPU {7AC6357C-BDA0-40AE-955E-953C4BFF5BB0}.Release|x86.ActiveCfg = Release|Any CPU {7AC6357C-BDA0-40AE-955E-953C4BFF5BB0}.Release|x86.Build.0 = Release|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Debug|x64.ActiveCfg = Debug|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Debug|x64.Build.0 = Debug|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Debug|x86.ActiveCfg = Debug|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Debug|x86.Build.0 = Debug|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Release|Any CPU.Build.0 = Release|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Release|x64.ActiveCfg = Release|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Release|x64.Build.0 = Release|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Release|x86.ActiveCfg = Release|Any CPU - {E72A14FF-5026-463B-B0FA-2DA104D67B0C}.Release|x86.Build.0 = Release|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Debug|Any CPU.Build.0 = Debug|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Debug|x64.ActiveCfg = Debug|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Debug|x64.Build.0 = Debug|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Debug|x86.ActiveCfg = Debug|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Debug|x86.Build.0 = Debug|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Release|Any CPU.ActiveCfg = Release|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Release|Any CPU.Build.0 = Release|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Release|x64.ActiveCfg = Release|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Release|x64.Build.0 = Release|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Release|x86.ActiveCfg = Release|Any CPU - {96E12F19-B25A-415E-B965-F9DE8D713C67}.Release|x86.Build.0 = Release|Any CPU {60678E53-EDC4-4ADE-A9EE-B194BDC76B37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {60678E53-EDC4-4ADE-A9EE-B194BDC76B37}.Debug|Any CPU.Build.0 = Debug|Any CPU {60678E53-EDC4-4ADE-A9EE-B194BDC76B37}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -205,24 +162,98 @@ Global {6DAD5C65-64CA-4ED4-B609-2D068F021024}.Release|x64.Build.0 = Release|Any CPU {6DAD5C65-64CA-4ED4-B609-2D068F021024}.Release|x86.ActiveCfg = Release|Any CPU {6DAD5C65-64CA-4ED4-B609-2D068F021024}.Release|x86.Build.0 = Release|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Debug|x64.ActiveCfg = Debug|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Debug|x64.Build.0 = Debug|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Debug|x86.ActiveCfg = Debug|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Debug|x86.Build.0 = Debug|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Release|Any CPU.Build.0 = Release|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Release|x64.ActiveCfg = Release|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Release|x64.Build.0 = Release|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Release|x86.ActiveCfg = Release|Any CPU + {ADD70570-8B1B-43C6-88DD-DE01612F19B6}.Release|x86.Build.0 = Release|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Debug|x64.ActiveCfg = Debug|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Debug|x64.Build.0 = Debug|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Debug|x86.ActiveCfg = Debug|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Debug|x86.Build.0 = Debug|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Release|Any CPU.Build.0 = Release|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Release|x64.ActiveCfg = Release|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Release|x64.Build.0 = Release|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Release|x86.ActiveCfg = Release|Any CPU + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F}.Release|x86.Build.0 = Release|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Debug|x64.ActiveCfg = Debug|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Debug|x64.Build.0 = Debug|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Debug|x86.ActiveCfg = Debug|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Debug|x86.Build.0 = Debug|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Release|Any CPU.Build.0 = Release|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Release|x64.ActiveCfg = Release|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Release|x64.Build.0 = Release|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Release|x86.ActiveCfg = Release|Any CPU + {BCA94498-0C74-4EBF-94BB-3A90A6996204}.Release|x86.Build.0 = Release|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Debug|x64.ActiveCfg = Debug|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Debug|x64.Build.0 = Debug|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Debug|x86.ActiveCfg = Debug|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Debug|x86.Build.0 = Debug|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Release|Any CPU.Build.0 = Release|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Release|x64.ActiveCfg = Release|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Release|x64.Build.0 = Release|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Release|x86.ActiveCfg = Release|Any CPU + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69}.Release|x86.Build.0 = Release|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Debug|x64.ActiveCfg = Debug|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Debug|x64.Build.0 = Debug|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Debug|x86.ActiveCfg = Debug|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Debug|x86.Build.0 = Debug|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Release|Any CPU.Build.0 = Release|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Release|x64.ActiveCfg = Release|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Release|x64.Build.0 = Release|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Release|x86.ActiveCfg = Release|Any CPU + {248FFB22-4BDD-40FA-A625-D957C1989A1B}.Release|x86.Build.0 = Release|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Debug|Any CPU.Build.0 = Debug|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Debug|x64.ActiveCfg = Debug|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Debug|x64.Build.0 = Debug|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Debug|x86.ActiveCfg = Debug|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Debug|x86.Build.0 = Debug|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Release|Any CPU.ActiveCfg = Release|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Release|Any CPU.Build.0 = Release|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Release|x64.ActiveCfg = Release|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Release|x64.Build.0 = Release|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Release|x86.ActiveCfg = Release|Any CPU + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {601DB071-B467-4237-9403-E63616038B61} = {1CF1274C-DE28-4446-9B4E-5884E797B87B} - {1F35ED8F-3E35-4D95-8E5C-44FCE3BA57D5} = {1CF1274C-DE28-4446-9B4E-5884E797B87B} {CBA2E524-B861-44FE-A0B0-668E57FF2A24} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} {A89CB3BC-7C15-4A71-863C-2E1DDEDDD12A} = {1CF1274C-DE28-4446-9B4E-5884E797B87B} {544DA4BF-E0DB-4222-B5DB-E9A7B9E2A5DD} = {276B4810-B0CB-4FDF-9CED-49B3DD59B19F} - {C7DF552E-DDE1-4D6D-B0A3-B9D273FC0E32} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} {5F8EBA76-7B6B-4BAF-9426-F17B14FA5C4C} = {1CF1274C-DE28-4446-9B4E-5884E797B87B} {7AC6357C-BDA0-40AE-955E-953C4BFF5BB0} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} - {E72A14FF-5026-463B-B0FA-2DA104D67B0C} = {1CF1274C-DE28-4446-9B4E-5884E797B87B} - {96E12F19-B25A-415E-B965-F9DE8D713C67} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} {ADCF7D08-F2EE-4DFD-A96A-7E0134A1546F} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} {60678E53-EDC4-4ADE-A9EE-B194BDC76B37} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} {6DAD5C65-64CA-4ED4-B609-2D068F021024} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} + {ADD70570-8B1B-43C6-88DD-DE01612F19B6} = {1CF1274C-DE28-4446-9B4E-5884E797B87B} + {6262163F-7E77-4BBD-B5FF-73EDE1AB203F} = {1CF1274C-DE28-4446-9B4E-5884E797B87B} + {BCA94498-0C74-4EBF-94BB-3A90A6996204} = {1CF1274C-DE28-4446-9B4E-5884E797B87B} + {2A1FE9D4-2FBF-46F3-AD1F-3A9728CECE69} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} + {248FFB22-4BDD-40FA-A625-D957C1989A1B} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} + {935BE8E7-FA7F-4C8F-A1D7-7CAFDC29F288} = {F77AD108-C6B4-46BB-B7BC-13573F45F876} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0EDE6697-0F13-4DB1-AC56-12C15A72D395} diff --git a/README.md b/README.md index 3f04289e..0177a515 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# FsSpreadsheet +# FsSpreadsheet Spreadsheet creation and manipulation in FSharp ## DSL @@ -65,22 +65,46 @@ tables ``` -## Develop +## Development -### Build QuickStart +### Requirements -If not already done, -1. install .NET SDK -2. install Node.js +- [nodejs and npm](https://nodejs.org/en/download) + - verify with `node --version` (Tested with v18.16.1) + - verify with `npm --version` (Tested with v9.2.0) +- [.NET SDK](https://dotnet.microsoft.com/en-us/download) + - verify with `dotnet --version` (Tested with 7.0.306) +- [Python](https://www.python.org/downloads/) + - verify with `py --version` (Tested with 3.12.2) + +### Local Setup + +1. Setup dotnet tools + + `dotnet tool restore` + +2. Install NPM dependencies + + `npm install` + +3. Setup python environment + + `py -m venv .venv` + +4. Install [Poetry](https://python-poetry.org/) and dependencies + + 1. `.\.venv\Scripts\python.exe -m pip install -U pip setuptools` + 2. `.\.venv\Scripts\python.exe -m pip install poetry` + 3. `.\.venv\Scripts\python.exe -m poetry install --no-root` + +Verify correct setup with `./build.cmd runtests` -In any shell, run -1. `dotnet tool restore` -4. `npm install` 5. `build.cmd ` where `` may be - if `` is empty, it just runs dotnet build after cleaning everything - `runtests` to run unit tests - `runtestsjs` to only run JS unit tests - `runtestsdotnet` to only run .NET unit tests + - `runtestpy` to only run Python unit tests - `releasenotes semver:` where `` may be `major`, `minor`, or `patch` to update RELEASE_NOTES.md - `pack` to create a NuGet release - `packprelease` to create a NuGet prerelease @@ -88,5 +112,4 @@ In any shell, run - `builddocsprerelease` to create prerelease docs - `watchdocs` to create docs and run them locally - `watchdocsprelease` to create prerelease docs and run them locally - - `publishnuget` to create a NuGet release and publish it - - `publishnugetprelease` to create a NuGet prerelease and publish it + - `release` to create a NuGet, NPM, PyPI and GitHub release diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 51fb5e57..8b74fc3e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,15 @@ +### 5.2.0+bbba6d4 (Released 2024-2-23) +* Additions: + * [[#bbba6d4](https://github.com/CSBiology/FsSpreadsheet/commit/bbba6d4ab819900f5188af3b5663d4744061991a)] start setup of python package + * [[#80dd1b6](https://github.com/CSBiology/FsSpreadsheet/commit/80dd1b608e46e7cda7646ea7c39619c0c7738f8e)] add tests for python xlsx io + * [[#992fa5a](https://github.com/CSBiology/FsSpreadsheet/commit/992fa5ac485313efc71285347b156b83614585d0)] add python xlsx io support + * [[#ddcc16d](https://github.com/CSBiology/FsSpreadsheet/commit/ddcc16dbdc51da516f53cbc3192d114584bd73fb)] add runtestspy target + * [[#d69288a](https://github.com/CSBiology/FsSpreadsheet/commit/d69288a33f1a259987cf4c229671723eaaf5beb2)] switch to pyxpecto for testing + * [[#2b88258](https://github.com/CSBiology/FsSpreadsheet/commit/2b882586b12aae0500eaad98d01603521dfee26f)] small speed improvement of reader by skipping sst include on opendocument cell +* Bugfixes: + * [[#b35f309](https://github.com/CSBiology/FsSpreadsheet/commit/b35f30908a4a68d8e3870c30cb8ace2dde748a7b)] finalize python xlsx io test and fixes + * [[#a55336e](https://github.com/CSBiology/FsSpreadsheet/commit/a55336ec03d5d2f1a254d2908d06d9b5381c7d55)] fix python xlsx io for default formats + ### 5.1.3+a260549 (Released 2024-2-13) * Additions: * [[#a260549](https://github.com/CSBiology/FsSpreadsheet/commit/a26054928881975896f2c07926261091979216a4)] update tests to change in empty workbook handling @@ -42,7 +54,7 @@ * [[#c5bf348](https://github.com/CSBiology/FsSpreadsheet/commit/c5bf34808d105723738dde53e6cb778a2b97da3e)] Finish io tests :heavy_check_mark: * [[#80f7632](https://github.com/CSBiology/FsSpreadsheet/commit/80f7632b2a4865951f144fc271e02a2ee4f6989c)] Improve DateTime numberFormat recognition * [[#baa88ce](https://github.com/CSBiology/FsSpreadsheet/commit/baa88ceb185c43302c8e7742ba8fe1afab893739)] update libre test file - * [[#9805811](https://github.com/CSBiology/FsSpreadsheet/commit/980581193cdcceaa80cd87f91e86121726c1046f)] Setup current FsSpreadsheet.Exceljs write for defaultio tests :construction: + * [[#9805811](https://github.com/CSBiology/FsSpreadsheet/commit/980581193cdcceaa80cd87f91e86121726c1046f)] Setup current FsSpreadsheet.Js write for defaultio tests :construction: * [[#05e0ca4](https://github.com/CSBiology/FsSpreadsheet/commit/05e0ca492e3ae54cdaf6fdec4c19c1296614e565)] update gitignore * [[#2b99506](https://github.com/CSBiology/FsSpreadsheet/commit/2b99506e9abafd7d579d8e3f09fb59d7e20a8398)] Further work on #71 change FsCell.Value to obj :boom: * [[#546e029](https://github.com/CSBiology/FsSpreadsheet/commit/546e02962c5d18127e143d85705523a4163d63c2)] add stylesheet helper functions @@ -112,11 +124,11 @@ * [[#95c5d16](https://github.com/CSBiology/FsSpreadsheet/commit/95c5d167403cb5a3323782b2e6895c66c9f1ebd8)] Push WIP state * [[#58b57ae](https://github.com/CSBiology/FsSpreadsheet/commit/58b57ae74d7d5d98e6146c75ce31eb819c0ed5d9)] Start refactoring to resizeArray :hammer:#53 * [[#5ed3752](https://github.com/CSBiology/FsSpreadsheet/commit/5ed37521a61683dfb6f6240a1c807474f50b9574)] Specify code snippet - * [[#4a9ff2e](https://github.com/CSBiology/FsSpreadsheet/commit/4a9ff2e91cf16c3d7d5587937f9c97d0c348e967)] Initiate test setup for FsSpreadsheet.Exceljs + * [[#4a9ff2e](https://github.com/CSBiology/FsSpreadsheet/commit/4a9ff2e91cf16c3d7d5587937f9c97d0c348e967)] Initiate test setup for FsSpreadsheet.Js * [[#d785795](https://github.com/CSBiology/FsSpreadsheet/commit/d785795061967c0206855983eebf49f1f182fe86)] Finish Api for both f# fable access and js native :sparkles: * [[#1456337](https://github.com/CSBiology/FsSpreadsheet/commit/1456337f88c8af863fb24bf134a93580ef5ed8b6)] update gitignore * [[#97f712c](https://github.com/CSBiology/FsSpreadsheet/commit/97f712cfe1d8422835a50c0186e28fc5cd2fcc4a)] setup msbuild - * [[#efa9815](https://github.com/CSBiology/FsSpreadsheet/commit/efa981573a24015d110a70c2e306e2678a5a36d5)] Init FsSpreadsheet.Exceljs and add Fable.Exceljs dependency + * [[#efa9815](https://github.com/CSBiology/FsSpreadsheet/commit/efa981573a24015d110a70c2e306e2678a5a36d5)] Init FsSpreadsheet.Js and add Fable.Exceljs dependency * [[#c4fdce6](https://github.com/CSBiology/FsSpreadsheet/commit/c4fdce69ea59a6a7da12fd190249a8e2f8d43136)] improve testsuit * [[#33eb847](https://github.com/CSBiology/FsSpreadsheet/commit/33eb84701d24d145cef5801966bf25844a8a7931)] cleanup test tasks * [[#3116aae](https://github.com/CSBiology/FsSpreadsheet/commit/3116aae6831fddcccc552d9d68b1bf4a565578ec)] Add dotnet tool femto diff --git a/build.cmd b/build.cmd index 139932b8..fe247e50 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,6 @@ @echo off + +set PYTHONIOENCODING=utf-8 +dotnet tool restore +cls dotnet run --project ./build/build.fsproj %* \ No newline at end of file diff --git a/build/BasicTasks.fs b/build/BasicTasks.fs index b6fe9cfc..d377af48 100644 --- a/build/BasicTasks.fs +++ b/build/BasicTasks.fs @@ -94,6 +94,14 @@ module Helper = createProcess npmPath + let python = + if System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows) then + Fake.Core.Trace.log "Detected Windows System." + createProcess (__SOURCE_DIRECTORY__.Replace(@"\build",@"\.venv\Scripts\python.exe")) + else + Fake.Core.Trace.log "Detected Unix System." + createProcess (__SOURCE_DIRECTORY__.Replace(@"/build",@"/.venv/bin/python")) + let run proc arg dir = proc arg dir |> Proc.run @@ -117,7 +125,7 @@ let clean = BuildTask.create "Clean" [] { ++ "src/**/obj" ++ "tests/**/bin" ++ "tests/**/obj" - ++ "pkg" + ++ "dist" |> Shell.cleanDirs } diff --git a/build/Build.fs b/build/Build.fs index 9f07e1a5..071a00c6 100644 --- a/build/Build.fs +++ b/build/Build.fs @@ -22,7 +22,7 @@ open ReleaseTasks let _release = BuildTask.createEmpty "Release" - [clean; build; runTests; pack; buildDocs; createTag; publishNuget; publishNPM; releaseDocs] + [clean; build; runTests; pack; buildDocs; createTag; publishNuget; publishNPM; publishPyPi; releaseDocs] /// Full release of nuget package, git tag, and documentation for the prerelease version. let _preRelease = diff --git a/build/PackageTasks.fs b/build/PackageTasks.fs index 029e896e..da0b733a 100644 --- a/build/PackageTasks.fs +++ b/build/PackageTasks.fs @@ -1,7 +1,5 @@ module PackageTasks -open ProjectInfo - open MessagePrompts open BasicTasks open TestTasks @@ -17,54 +15,38 @@ let private replaceCommitLink input = let commitLinkPattern = @"\[\[#[a-z0-9]*\]\(.*\)\] " Regex.Replace(input,commitLinkPattern,"") -let packDotNet = BuildTask.create "PackDotNet" [clean; build; runTests] { - if promptYesNo (sprintf "[.NET] creating stable package with version %s OK?" stableVersionTag ) - then - !! "src/**/*.*proj" - -- "src/bin/*" - |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> - let msBuildParams = - {p.MSBuildParams with - Properties = ([ - "Version",stableVersionTag - "PackageReleaseNotes", (release.Notes |> List.map replaceCommitLink |> String.concat "\r\n" ) - ] @ p.MSBuildParams.Properties) - } - { - p with - MSBuildParams = msBuildParams - OutputPath = Some pkgDir +module BundleDotNet = + let bundle (versionTag : string) (versionSuffix : string option) = + System.IO.Directory.CreateDirectory(ProjectInfo.netPkgDir) |> ignore + !! "src/**/*.*proj" + -- "src/bin/*" + |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> + let msBuildParams = + {p.MSBuildParams with + Properties = ([ + "Version",versionTag + "PackageReleaseNotes", (ProjectInfo.release.Notes |> List.map replaceCommitLink |> String.toLines ) + ] @ p.MSBuildParams.Properties) } - )) - else failwith "aborted" + { + p with + VersionSuffix = versionSuffix + MSBuildParams = msBuildParams + OutputPath = Some ProjectInfo.netPkgDir + } + )) + +let packDotNet = BuildTask.create "PackDotNet" [clean; build; runTests] { + BundleDotNet.bundle ProjectInfo.stableVersionTag None } let packDotNetPrerelease = BuildTask.create "PackDotNetPrerelease" [setPrereleaseTag; clean; build; runTests] { - if promptYesNo (sprintf "[.NET] creating prerelease package with version %s OK?" prereleaseTag ) - then - !! "src/**/*.*proj" - -- "src/bin/*" - |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> - let msBuildParams = - {p.MSBuildParams with - Properties = ([ - "Version", prereleaseTag - "PackageReleaseNotes", (release.Notes |> List.map replaceCommitLink |> String.toLines ) - ] @ p.MSBuildParams.Properties) - } - { - p with - VersionSuffix = Some prereleaseSuffix - OutputPath = Some pkgDir - MSBuildParams = msBuildParams - } - )) - else - failwith "aborted" + BundleDotNet.bundle ProjectInfo.prereleaseTag (Some ProjectInfo.prereleaseTag) } module BundleJs = let bundle (versionTag) = + System.IO.Directory.CreateDirectory(ProjectInfo.npmPkgDir) |> ignore run npm "run bundle" "" Fake.IO.File.readAsString "package.json" |> fun t -> @@ -74,17 +56,34 @@ module BundleJs = |> Fake.IO.File.writeString false $"{ProjectInfo.npmPkgDir}/fable_modules/.npmignore" let packJS = BuildTask.create "PackJS" [clean; build; runTests] { - if promptYesNo (sprintf "[NPM] creating stable package with version %s OK?" ProjectInfo.stableVersionTag ) - then - BundleJs.bundle ProjectInfo.stableVersionTag - else failwith "aborted" + BundleJs.bundle ProjectInfo.stableVersionTag } let packJSPrerelease = BuildTask.create "PackJSPrerelease" [setPrereleaseTag; clean; build; runTests] { - if promptYesNo (sprintf "[NPM] creating prerelease package with version %s OK?" ProjectInfo.prereleaseTag ) then - BundleJs.bundle ProjectInfo.prereleaseTag - else failwith "aborted" + BundleJs.bundle ProjectInfo.prereleaseTag } -let pack = BuildTask.createEmpty "Pack" [packDotNet; packJS] -let packPrerelease = BuildTask.createEmpty "PackPrerelease" [packDotNetPrerelease;packJSPrerelease] \ No newline at end of file +module BundlePy = + let bundle (versionTag: string) = + + run dotnet $"fable src/FsSpreadsheet.Py -o {ProjectInfo.pyPkgDir}/fsspreadsheet --lang python" "" + run python "-m poetry install --no-root" ProjectInfo.pyPkgDir + //GenerateIndexPy.ARCtrl_generate (ProjectInfo.pyPkgDir + "/arctrl") + + Fake.IO.File.readAsString "pyproject.toml" + |> fun t -> + let t = t.Replace(ProjectInfo.stableVersionTag, versionTag) + Fake.IO.File.writeString false $"{ProjectInfo.pyPkgDir}/pyproject.toml" t + + Fake.IO.File.readAsString "README.md" + |> Fake.IO.File.writeString false $"{ProjectInfo.pyPkgDir}/README.md" + + run python "-m poetry build" ProjectInfo.pyPkgDir //Remove "-o ." because not compatible with publish + +let packPy = BuildTask.create "PackPy" [clean; build; runTests] { + BundlePy.bundle ProjectInfo.stableVersionTag +} + +let pack = BuildTask.createEmpty "Pack" [packDotNet; packJS; packPy] + +let packPrerelease = BuildTask.createEmpty "PackPrerelease" [packDotNetPrerelease; packJSPrerelease] \ No newline at end of file diff --git a/build/ProjectInfo.fs b/build/ProjectInfo.fs index 2be9d678..96360214 100644 --- a/build/ProjectInfo.fs +++ b/build/ProjectInfo.fs @@ -7,7 +7,7 @@ let project = "FsSpreadsheet" let testProjects = [ "tests/FsSpreadsheet.Tests" - "tests/FsSpreadsheet.ExcelIO.Tests" + "tests/FsSpreadsheet.Net.Tests" "tests/FsSpreadsheet.Interactive.Tests" ] @@ -21,8 +21,9 @@ let gitHome = $"https://github.com/{gitOwner}" let projectRepo = $"https://github.com/{gitOwner}/{project}" -let pkgDir = "pkg" -let npmPkgDir = "dist" +let netPkgDir = "dist/net" +let npmPkgDir = "dist/js" +let pyPkgDir = "dist/py" // Create RELEASE_NOTES.md if not existing. Or "release" would throw an error. Fake.Extensions.Release.ReleaseNotes.ensure() diff --git a/build/ReleaseTasks.fs b/build/ReleaseTasks.fs index 4f267dc2..6eafaae2 100644 --- a/build/ReleaseTasks.fs +++ b/build/ReleaseTasks.fs @@ -33,7 +33,7 @@ let createPrereleaseTag = BuildTask.create "CreatePrereleaseTag" [setPrereleaseT let publishNuget = BuildTask.create "PublishNuget" [clean; build; runTests; packDotNet] { - let targets = (!! (sprintf "%s/*.*pkg" pkgDir )) + let targets = (!! (sprintf "%s/*.*pkg" netPkgDir )) for target in targets do printfn "%A" target let msg = sprintf "[.NET] release package with version %s?" stableVersionTag if promptYesNo msg then @@ -46,7 +46,7 @@ let publishNuget = BuildTask.create "PublishNuget" [clean; build; runTests; pack } let publishNugetPrerelease = BuildTask.create "PublishNugetPrerelease" [clean; build; runTests; packDotNetPrerelease] { - let targets = (!! (sprintf "%s/*.*pkg" pkgDir )) + let targets = (!! (sprintf "%s/*.*pkg" netPkgDir )) for target in targets do printfn "%A" target let msg = sprintf "[.NET] release package with version %s?" prereleaseTag if promptYesNo msg then @@ -76,6 +76,18 @@ let publishNPMPrerelease = BuildTask.create "PublishNPMPrerelease" [clean; build else failwith "aborted" } +let publishPyPi = BuildTask.create "PublishPyPi" [packPy] { + let msg = sprintf "[PyPi] release package with version %s?" stableVersionTag + if promptYesNo msg then + let apikey = Environment.environVarOrNone "PYPI_KEY" + match apikey with + | Some key -> + run python $"-m poetry config pypi-token.pypi {key}" ProjectInfo.pyPkgDir + | None -> () + run python "-m poetry publish" ProjectInfo.pyPkgDir + else failwith "aborted" +} + let releaseDocs = BuildTask.create "ReleaseDocs" [buildDocs] { let msg = sprintf "release docs for version %s?" stableVersionTag if promptYesNo msg then diff --git a/build/TestTasks.fs b/build/TestTasks.fs index 3a16a5d3..7d1bd86d 100644 --- a/build/TestTasks.fs +++ b/build/TestTasks.fs @@ -42,20 +42,26 @@ module RunTests = run npm "run testjs" "" } + let runTestsPy = BuildTask.create "runTestsPy" [clean; build] { + let testProjectsPy = + [ + "tests/FsSpreadsheet.Tests" + "tests/FsSpreadsheet.Py.Tests" + ] + for path in testProjectsPy do + //transpile py files from fsharp code + run dotnet $"fable {path} -o {path}/py --lang python" "" + // run pyxpecto in target path to execute tests in python + run python $"{path}/py/main.py" "" + } + let runTestsDotnet = BuildTask.create "runTestsDotnet" [clean; build] { testProjects |> Seq.iter (fun testProject -> - Fake.DotNet.DotNet.test(fun testParams -> - { - testParams with - Logger = Some "console;verbosity=detailed" - Configuration = DotNet.BuildConfiguration.fromString configuration - NoBuild = true - } - ) testProject + run dotnet $"run" testProject ) } -let runTests = BuildTask.create "RunTests" [clean; build; RunTests.runTestsJs; RunTests.runTestsDotnet] { +let runTests = BuildTask.create "RunTests" [clean; build; RunTests.runTestsJs; RunTests.runTestsDotnet; RunTests.runTestsPy] { () } \ No newline at end of file diff --git a/package.json b/package.json index 174266f0..051e2a68 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,18 @@ { "name": "@fslab/fsspreadsheet", - "version": "5.1.3", + "version": "5.2.0", "description": "Minimal spreadsheet creation and manipulation using exceljs io.", "type": "module", "main": "Xlsx.js", "scripts": { "pretest": "dotnet fable tests/FsSpreadsheet.Tests --noCache -o tests/FsSpreadsheet.Tests/js", - "test": "mocha tests/FsSpreadsheet.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", - "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" + "test": "node tests/FsSpreadsheet.Tests/js/Main.js", + "pretestexceljs": "dotnet fable tests/FsSpreadsheet.Js.Tests --noCache -o tests/FsSpreadsheet.Js.Tests/js", + "testexceljs": "node tests/FsSpreadsheet.Js.Tests/js/Main.js", + "pretestjs": "dotnet fable src/FsSpreadsheet.Js --noCache -o tests/JS/FsSpreadsheet.Js", + "testjs": "mocha tests/JS", + "prebundle": "mkdir dist/js & dotnet fable clean --extension .js --yes -o dist/js", + "bundle": "dotnet fable src/FsSpreadsheet.Js -o dist/js" }, "repository": { "type": "git", diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..741391d7 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,31 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "et-xmlfile" +version = "1.1.0" +description = "An implementation of lxml.xmlfile for the standard library" +optional = false +python-versions = ">=3.6" +files = [ + {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"}, + {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"}, +] + +[[package]] +name = "openpyxl" +version = "3.1.2" +description = "A Python library to read/write Excel 2010 xlsx/xlsm files" +optional = false +python-versions = ">=3.6" +files = [ + {file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"}, + {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"}, +] + +[package.dependencies] +et-xmlfile = "*" + +[metadata] +lock-version = "2.0" +python-versions = ">= 3.11, < 4.0" +content-hash = "b2fb39bf113af5a101171454ce20dcaa9b067b057d2022003de30db63a810d5f" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..35fdfa97 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,20 @@ +[tool.poetry] +name = "fsspreadsheet" +version = "5.2.0" +description = "Fable library for Spreadsheet creation and manipulation" +authors = ["Heinrich Lukas Weil ", "Kevin Frey "] +maintainers = ["Oliver Maus"] +license = "MIT License" +readme = "README.md" +homepage = "https://fslab.org/FsSpreadsheet/" +repository = "https://github.com/fslaborg/FsSpreadsheet" +documentation = "https://fslab.org/FsSpreadsheet/" + +[tool.poetry.dependencies] +python = ">= 3.11, < 4.0" +openpyxl = ">=3.1.2" +et-xmlfile = ">=1.1.0" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" \ No newline at end of file diff --git a/src/FsSpreadsheet.Exceljs/Cell.fs b/src/FsSpreadsheet.Js/Cell.fs similarity index 99% rename from src/FsSpreadsheet.Exceljs/Cell.fs rename to src/FsSpreadsheet.Js/Cell.fs index 6fec03d2..e0fdfed9 100644 --- a/src/FsSpreadsheet.Exceljs/Cell.fs +++ b/src/FsSpreadsheet.Js/Cell.fs @@ -1,4 +1,4 @@ -namespace FsSpreadsheet.Exceljs +namespace FsSpreadsheet.Js module JsCell = diff --git a/src/FsSpreadsheet.Exceljs/FsExtensions.fs b/src/FsSpreadsheet.Js/FsExtensions.fs similarity index 94% rename from src/FsSpreadsheet.Exceljs/FsExtensions.fs rename to src/FsSpreadsheet.Js/FsExtensions.fs index d4645240..fe57837d 100644 --- a/src/FsSpreadsheet.Exceljs/FsExtensions.fs +++ b/src/FsSpreadsheet.Js/FsExtensions.fs @@ -1,8 +1,8 @@ [] -module FsSpreadsheet.Exceljs.FsSpreadsheet +module FsSpreadsheet.Js.FsSpreadsheet open FsSpreadsheet -open FsSpreadsheet.Exceljs +open FsSpreadsheet.Js open Fable.Core open Fable.Core.JS open Fable.Core.JsInterop diff --git a/src/FsSpreadsheet.Exceljs/FsSpreadsheet.Exceljs.fsproj b/src/FsSpreadsheet.Js/FsSpreadsheet.Js.fsproj similarity index 97% rename from src/FsSpreadsheet.Exceljs/FsSpreadsheet.Exceljs.fsproj rename to src/FsSpreadsheet.Js/FsSpreadsheet.Js.fsproj index dc34d853..f380206c 100644 --- a/src/FsSpreadsheet.Exceljs/FsSpreadsheet.Exceljs.fsproj +++ b/src/FsSpreadsheet.Js/FsSpreadsheet.Js.fsproj @@ -1,50 +1,50 @@ - - - - Kevin Frey, Heinrich Lukas Weil, Oliver Maus, Kevin Schneider, Timo Mühlhaus - Excel IO Extensions for the FsSpreadsheet Datamodel in js environments using exceljs. - Spreadsheet creation and manipulation in FSharp - MIT - logo.png - F# FSharp spreadsheet Excel xlsx datascience fable fable-library fable-javascript - https://github.com/CSBiology/FsSpreadsheet - git - - - - netstandard2.0 - true - - - - - \ - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Kevin Frey, Heinrich Lukas Weil, Oliver Maus, Kevin Schneider, Timo Mühlhaus + Excel IO Extensions for the FsSpreadsheet Datamodel in js environments using exceljs. + Spreadsheet creation and manipulation in FSharp + MIT + logo.png + F# FSharp spreadsheet Excel xlsx datascience fable fable-library fable-javascript + https://github.com/CSBiology/FsSpreadsheet + git + + + + netstandard2.0 + true + + + + + \ + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FsSpreadsheet.Exceljs/Table.fs b/src/FsSpreadsheet.Js/Table.fs similarity index 98% rename from src/FsSpreadsheet.Exceljs/Table.fs rename to src/FsSpreadsheet.Js/Table.fs index 58359f08..fafbab83 100644 --- a/src/FsSpreadsheet.Exceljs/Table.fs +++ b/src/FsSpreadsheet.Js/Table.fs @@ -1,4 +1,4 @@ -namespace FsSpreadsheet.Exceljs +namespace FsSpreadsheet.Js module JsTable = diff --git a/src/FsSpreadsheet.Exceljs/Workbook.fs b/src/FsSpreadsheet.Js/Workbook.fs similarity index 99% rename from src/FsSpreadsheet.Exceljs/Workbook.fs rename to src/FsSpreadsheet.Js/Workbook.fs index a53c3d2e..dc719e8d 100644 --- a/src/FsSpreadsheet.Exceljs/Workbook.fs +++ b/src/FsSpreadsheet.Js/Workbook.fs @@ -1,4 +1,4 @@ -namespace FsSpreadsheet.Exceljs +namespace FsSpreadsheet.Js module JsWorkbook = open FsSpreadsheet diff --git a/src/FsSpreadsheet.Exceljs/Worksheet.fs b/src/FsSpreadsheet.Js/Worksheet.fs similarity index 97% rename from src/FsSpreadsheet.Exceljs/Worksheet.fs rename to src/FsSpreadsheet.Js/Worksheet.fs index ecbcfb09..4771b581 100644 --- a/src/FsSpreadsheet.Exceljs/Worksheet.fs +++ b/src/FsSpreadsheet.Js/Worksheet.fs @@ -1,4 +1,4 @@ -namespace FsSpreadsheet.Exceljs +namespace FsSpreadsheet.Js module JsWorksheet = diff --git a/src/FsSpreadsheet.Exceljs/Xlsx.fs b/src/FsSpreadsheet.Js/Xlsx.fs similarity index 97% rename from src/FsSpreadsheet.Exceljs/Xlsx.fs rename to src/FsSpreadsheet.Js/Xlsx.fs index aa5af836..a3d6206b 100644 --- a/src/FsSpreadsheet.Exceljs/Xlsx.fs +++ b/src/FsSpreadsheet.Js/Xlsx.fs @@ -1,4 +1,4 @@ -namespace FsSpreadsheet.Exceljs +namespace FsSpreadsheet.Js open FsSpreadsheet open Fable.ExcelJs diff --git a/src/FsSpreadsheet.ExcelIO/Cell.fs b/src/FsSpreadsheet.Net/Cell.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/Cell.fs rename to src/FsSpreadsheet.Net/Cell.fs diff --git a/src/FsSpreadsheet.ExcelIO/CellData.fs b/src/FsSpreadsheet.Net/CellData.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/CellData.fs rename to src/FsSpreadsheet.Net/CellData.fs diff --git a/src/FsSpreadsheet.ExcelIO/FsExtensions.fs b/src/FsSpreadsheet.Net/FsExtensions.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/FsExtensions.fs rename to src/FsSpreadsheet.Net/FsExtensions.fs diff --git a/src/FsSpreadsheet.ExcelIO/FsSpreadsheet.ExcelIO.fsproj b/src/FsSpreadsheet.Net/FsSpreadsheet.Net.fsproj similarity index 98% rename from src/FsSpreadsheet.ExcelIO/FsSpreadsheet.ExcelIO.fsproj rename to src/FsSpreadsheet.Net/FsSpreadsheet.Net.fsproj index c73a10e5..5ebaf83c 100644 --- a/src/FsSpreadsheet.ExcelIO/FsSpreadsheet.ExcelIO.fsproj +++ b/src/FsSpreadsheet.Net/FsSpreadsheet.Net.fsproj @@ -1,60 +1,60 @@ - - - - netstandard2.0 - true - - - - Heinrich Lukas Weil, Oliver Maus, Kevin Schneider, Timo Mühlhaus - Excel IO Extensions for the FsSpreadsheet Datamodel - Excel IO Extensions for the FsSpreadsheet Datamodel - MIT - logo.png - F# FSharp spreadsheet xlsx datascience - https://github.com/CSBiology/FsSpreadsheet - git - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectReferenceWithExplicitPackageVersion Include="@(ProjectReference->'%(FullPath)')" Condition="'%(ProjectReference.PackageVersion)' != ''" /> - <_ProjectReferenceWithExactPackageVersion Include="@(ProjectReference->'%(FullPath)')" Condition="'%(ProjectReference.ExactVersion)' == 'true'" /> - <_ProjectReferenceWithReassignedVersion Include="@(_ProjectReferencesWithVersions)" Condition="'%(Identity)' != '' And '@(_ProjectReferenceWithExplicitPackageVersion)' == '@(_ProjectReferencesWithVersions)'"> - @(_ProjectReferenceWithExplicitPackageVersion->'%(PackageVersion)') - - <_ProjectReferenceWithReassignedVersion Include="@(_ProjectReferencesWithVersions)" Condition="'%(Identity)' != '' And '@(_ProjectReferenceWithExactPackageVersion)' == '@(_ProjectReferencesWithVersions)'"> - [@(_ProjectReferencesWithVersions->'%(ProjectVersion)')] - - <_ProjectReferencesWithVersions Remove="@(_ProjectReferenceWithReassignedVersion)" /> - <_ProjectReferencesWithVersions Include="@(_ProjectReferenceWithReassignedVersion)" /> - - - - + + + + netstandard2.0 + true + + + + Heinrich Lukas Weil, Oliver Maus, Kevin Schneider, Timo Mühlhaus + Excel IO Extensions for the FsSpreadsheet Datamodel + Excel IO Extensions for the FsSpreadsheet Datamodel + MIT + logo.png + F# FSharp spreadsheet xlsx datascience + https://github.com/CSBiology/FsSpreadsheet + git + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectReferenceWithExplicitPackageVersion Include="@(ProjectReference->'%(FullPath)')" Condition="'%(ProjectReference.PackageVersion)' != ''" /> + <_ProjectReferenceWithExactPackageVersion Include="@(ProjectReference->'%(FullPath)')" Condition="'%(ProjectReference.ExactVersion)' == 'true'" /> + <_ProjectReferenceWithReassignedVersion Include="@(_ProjectReferencesWithVersions)" Condition="'%(Identity)' != '' And '@(_ProjectReferenceWithExplicitPackageVersion)' == '@(_ProjectReferencesWithVersions)'"> + @(_ProjectReferenceWithExplicitPackageVersion->'%(PackageVersion)') + + <_ProjectReferenceWithReassignedVersion Include="@(_ProjectReferencesWithVersions)" Condition="'%(Identity)' != '' And '@(_ProjectReferenceWithExactPackageVersion)' == '@(_ProjectReferencesWithVersions)'"> + [@(_ProjectReferencesWithVersions->'%(ProjectVersion)')] + + <_ProjectReferencesWithVersions Remove="@(_ProjectReferenceWithReassignedVersion)" /> + <_ProjectReferencesWithVersions Include="@(_ProjectReferenceWithReassignedVersion)" /> + + + + diff --git a/src/FsSpreadsheet.ExcelIO/Package.fs b/src/FsSpreadsheet.Net/Package.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/Package.fs rename to src/FsSpreadsheet.Net/Package.fs diff --git a/src/FsSpreadsheet.ExcelIO/Row.fs b/src/FsSpreadsheet.Net/Row.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/Row.fs rename to src/FsSpreadsheet.Net/Row.fs diff --git a/src/FsSpreadsheet.ExcelIO/SharedStringTable.fs b/src/FsSpreadsheet.Net/SharedStringTable.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/SharedStringTable.fs rename to src/FsSpreadsheet.Net/SharedStringTable.fs diff --git a/src/FsSpreadsheet.ExcelIO/Sheet.fs b/src/FsSpreadsheet.Net/Sheet.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/Sheet.fs rename to src/FsSpreadsheet.Net/Sheet.fs diff --git a/src/FsSpreadsheet.ExcelIO/SheetData.fs b/src/FsSpreadsheet.Net/SheetData.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/SheetData.fs rename to src/FsSpreadsheet.Net/SheetData.fs diff --git a/src/FsSpreadsheet.ExcelIO/Spreadsheet.fs b/src/FsSpreadsheet.Net/Spreadsheet.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/Spreadsheet.fs rename to src/FsSpreadsheet.Net/Spreadsheet.fs diff --git a/src/FsSpreadsheet.ExcelIO/Stylesheet.fs b/src/FsSpreadsheet.Net/Stylesheet.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/Stylesheet.fs rename to src/FsSpreadsheet.Net/Stylesheet.fs diff --git a/src/FsSpreadsheet.ExcelIO/Table.fs b/src/FsSpreadsheet.Net/Table.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/Table.fs rename to src/FsSpreadsheet.Net/Table.fs diff --git a/src/FsSpreadsheet.ExcelIO/Workbook.fs b/src/FsSpreadsheet.Net/Workbook.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/Workbook.fs rename to src/FsSpreadsheet.Net/Workbook.fs diff --git a/src/FsSpreadsheet.ExcelIO/Worksheet.fs b/src/FsSpreadsheet.Net/Worksheet.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/Worksheet.fs rename to src/FsSpreadsheet.Net/Worksheet.fs diff --git a/src/FsSpreadsheet.ExcelIO/ZipArchiveReader.fs b/src/FsSpreadsheet.Net/ZipArchiveReader.fs similarity index 100% rename from src/FsSpreadsheet.ExcelIO/ZipArchiveReader.fs rename to src/FsSpreadsheet.Net/ZipArchiveReader.fs diff --git a/src/FsSpreadsheet.Py/Cell.fs b/src/FsSpreadsheet.Py/Cell.fs new file mode 100644 index 00000000..f6d2edcd --- /dev/null +++ b/src/FsSpreadsheet.Py/Cell.fs @@ -0,0 +1,65 @@ +namespace FsSpreadsheet.ExcelPy + +module PyCell = + + open Fable.Core + open Fable.Core.PyInterop + open FsSpreadsheet + open Fable.Openpyxl + + // Currently in Fable, a created datetime object will contain a timezone. This is not allowed in python xlsx, so we need to remove it. + // Unfortunately, the timezone object in python is read-only, so we need to create a new datetime object without timezone. + // For this, we use the fromtimestamp method of the datetime module and convert the timestamp to a new datetime object without timezone. + type datetime = + abstract member decoy: unit -> unit + type DateTimeStatic = + [] + abstract member fromTimeStamp: timestamp:float -> datetime + [] + let DateTime : DateTimeStatic = nativeOnly + + + let toUniversalTimePy (dt:System.DateTime) = + + dt.ToUniversalTime()?timestamp() + |> DateTime.fromTimeStamp + + let fromFsCell (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.ToUniversalTime() + dt.Offset |> box |> Some + //dt + let dt = fsCell.ValueAsDateTime() |> toUniversalTimePy |> box + //dt?tzinfo <- None + dt + |> Some + | String -> + fsCell.Value |> Some + | anyElse -> + let msg = sprintf "ValueType '%A' is not fully implemented in FsSpreadsheet and is handled as string input." anyElse + printfn "%s" msg + + fsCell.Value |> box |> Some + + let toFsCell worksheetName rowIndex columnIndex (pyCell: Cell) = + //printfn "toFsCell worksheetName: %s, rowIndex: %i, columnIndex: %i, %A" worksheetName rowIndex columnIndex (pyCell.value, pyCell.cellType) + let fsadress = FsAddress(rowIndex,columnIndex) + let dt,v = + let dt,v = DataType.InferCellValue pyCell.value + if v = "=TRUE()" || v = "=True()" then + Boolean,box true + elif v = "=FALSE()" || v = "=False()" then + Boolean,box false + else + dt,v + FsCell(v,dt,address = fsadress) + + + diff --git a/src/FsSpreadsheet.Py/CellType.fs b/src/FsSpreadsheet.Py/CellType.fs new file mode 100644 index 00000000..5739f11e --- /dev/null +++ b/src/FsSpreadsheet.Py/CellType.fs @@ -0,0 +1,31 @@ +namespace FsSpreadsheet.ExcelPy + +module PyCellType = + + open Fable.Core + open Fable.Core.JsInterop + open FsSpreadsheet + open Fable.Openpyxl + + let fromDataTyoe (t: DataType) = + match t with + | Boolean -> CellType.Boolean + | Number -> CellType.Float + | Date -> CellType.DateTime + | String -> CellType.String + | anyElse -> + let msg = sprintf "ValueType '%A' is not fully implemented in FsSpreadsheet and is handled as string input." anyElse + printfn "%s" msg + CellType.String + + let toDataType (t: CellType) = + match t with + | CellType.Boolean -> DataType.Boolean + | CellType.Float -> DataType.Number + | CellType.Integer -> DataType.Number + | CellType.DateTime -> DataType.Date + | CellType.String -> DataType.String + | anyElse -> + let msg = sprintf "ValueType '%A' is not fully implemented in FsSpreadsheet and is handled as string input." anyElse + printfn "%s" msg + DataType.String \ No newline at end of file diff --git a/src/FsSpreadsheet.Py/FsExtension.fs b/src/FsSpreadsheet.Py/FsExtension.fs new file mode 100644 index 00000000..3963b8c0 --- /dev/null +++ b/src/FsSpreadsheet.Py/FsExtension.fs @@ -0,0 +1,38 @@ +[] +module FsSpreadsheet.ExcelPy.FsSpreadsheet + +open FsSpreadsheet +open FsSpreadsheet.ExcelPy +open Fable.Core + +// This is mainly used for fsharp based access in a fable environment. +// If you want to use these bindings from js, you should use the ones in `Xlsx.fs` +type FsWorkbook with + + static member fromXlsxFile(path:string) : FsWorkbook = + Xlsx.fromXlsxFile path + + static member fromXlsxStream(stream:System.IO.Stream) : FsWorkbook = + Xlsx.fromXlsxStream stream + + static member fromBytes(bytes: byte []) : FsWorkbook = + Xlsx.fromBytes bytes + + static member toFile(path: string) (wb:FsWorkbook) : unit = + Xlsx.toFile path wb + + //static member toStream(stream: System.IO.Stream) (wb:FsWorkbook) : Promise = + // PyWorkbook.fromFsWorkbook wb + // |> fun wb -> Xlsx.writeBuffer(wb,stream) + + static member toBytes(wb:FsWorkbook) : byte [] = + Xlsx.toBytes wb + + member this.ToFile(path: string) : unit = + FsWorkbook.toFile path this + + //member this.ToStream(stream: System.IO.Stream) : unit = + // FsWorkbook.toStream stream this + + member this.ToBytes() : byte [] = + FsWorkbook.toBytes this \ No newline at end of file diff --git a/src/FsSpreadsheet.Py/FsSpreadsheet.Py.fsproj b/src/FsSpreadsheet.Py/FsSpreadsheet.Py.fsproj new file mode 100644 index 00000000..3b300a7a --- /dev/null +++ b/src/FsSpreadsheet.Py/FsSpreadsheet.Py.fsproj @@ -0,0 +1,28 @@ + + + + netstandard2.0 + true + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FsSpreadsheet.Py/Table.fs b/src/FsSpreadsheet.Py/Table.fs new file mode 100644 index 00000000..45f2fd35 --- /dev/null +++ b/src/FsSpreadsheet.Py/Table.fs @@ -0,0 +1,35 @@ +namespace FsSpreadsheet.ExcelPy + +module PyTable = + + open Fable.Core + open FsSpreadsheet + open Fable.Openpyxl + open Fable.Core.PyInterop + + + type tablestyle = + abstract member name: unit -> string + abstract member showFirstColumn: unit -> bool + abstract member showLastColumn: unit -> bool + abstract member showRowStripes: unit -> bool + abstract member showColumnStripes: unit -> bool + + type TableStyleStatic = + [] + abstract member create: name:string * showFirstColumn:bool * showLastColumn:bool * showRowStripes:bool * showColumnStripes:bool -> tablestyle + + [] + let TableStyleInfo : TableStyleStatic = nativeOnly + + let defaultTableStyle() = TableStyleInfo.create("TableStyleMedium9", false, false, true, true) + + let fromFsTable (fsTable: FsTable) : Table = + let table = Table.create(fsTable.Name,fsTable.RangeAddress.Range) + table?tableStyleInfo <- defaultTableStyle() + table + + let toFsTable(table:Table) = + let name = if isNull table.displayName then table.name else table.displayName + let ref = table.ref + FsTable(name,FsRangeAddress(ref)) diff --git a/src/FsSpreadsheet.Py/Workbook.fs b/src/FsSpreadsheet.Py/Workbook.fs new file mode 100644 index 00000000..5679b6c5 --- /dev/null +++ b/src/FsSpreadsheet.Py/Workbook.fs @@ -0,0 +1,30 @@ +namespace FsSpreadsheet.ExcelPy + +module PyWorkbook = + + open Fable.Core + open FsSpreadsheet + open Fable.Openpyxl + open Fable.Core.PyInterop + + let fromFsWorkbook (fsWB: FsWorkbook) : Workbook = + if fsWB.GetWorksheets().Count = 0 then + failwith "Workbook must contain at least one worksheet" + let pyWB = Workbook.create() + pyWB.remove(pyWB.active) + fsWB.GetWorksheets() + |> Seq.iter (fun ws -> + PyWorksheet.fromFsWorksheet pyWB ws |> ignore + ) + //if fsWB.TryGetWorksheetByName("Sheet").IsNone then + // pyWB + pyWB + + let toFsWorkbook(pyWB:Workbook) : FsWorkbook = + let fsWB = new FsWorkbook() + pyWB.worksheets |> Array.iter (fun (ws : Worksheet) -> + if ws.title <> "Sheet" && ws.values.Length <> 0 then + let w = PyWorksheet.toFsWorksheet ws + fsWB.AddWorksheet(w) |> ignore + ) + fsWB diff --git a/src/FsSpreadsheet.Py/Worksheet.fs b/src/FsSpreadsheet.Py/Worksheet.fs new file mode 100644 index 00000000..dc602256 --- /dev/null +++ b/src/FsSpreadsheet.Py/Worksheet.fs @@ -0,0 +1,38 @@ +namespace FsSpreadsheet.ExcelPy + +module PyWorksheet = + + open Fable.Core + open FsSpreadsheet + open Fable.Openpyxl + open Fable.Core.PyInterop + + let fromFsWorksheet (parent : Workbook) (fsWS: FsWorksheet) : Worksheet = + let pyWS = parent.create_sheet(fsWS.Name) + fsWS.Tables + |> Seq.iter (fun table -> + let pyTable = PyTable.fromFsTable table + pyWS.add_table(pyTable) |> ignore + ) + fsWS.CellCollection.GetCells() + |> Seq.iter (fun cell -> + let pyCell = PyCell.fromFsCell cell + pyWS.cell(cell.Address.RowNumber, cell.Address.ColumnNumber, pyCell) |> ignore + ) + pyWS + + + let toFsWorksheet(pyWS:Worksheet) : FsWorksheet = + let fsWS = FsWorksheet(pyWS.title) + pyWS.tables.values() |> Array.iter (fun table -> + let t = PyTable.toFsTable table + fsWS.AddTable(t) |> ignore + ) + pyWS.rows |> Array.iteri (fun rowIndex row -> + row |> Array.iteri (fun colIndex cell -> + if cell.cellType <> "NoneType" then + let c = PyCell.toFsCell pyWS.title (rowIndex + 1) (colIndex + 1) cell + fsWS.AddCell(c) |> ignore + ) + ) + fsWS diff --git a/src/FsSpreadsheet.Py/Xlsx.fs b/src/FsSpreadsheet.Py/Xlsx.fs new file mode 100644 index 00000000..1ea8738d --- /dev/null +++ b/src/FsSpreadsheet.Py/Xlsx.fs @@ -0,0 +1,36 @@ +namespace FsSpreadsheet.ExcelPy + + +open FsSpreadsheet +open FsSpreadsheet.ExcelPy +open Fable.Core +open Fable.Openpyxl + +/// This does currently not correctly work if you want to use this from js +/// https://github.com/fable-compiler/Fable/issues/3498 +[] +type Xlsx = + + static member fromXlsxFile(path:string) : FsWorkbook = + Xlsx.readFile path + |> PyWorkbook.toFsWorkbook + + static member fromXlsxStream(stream:System.IO.Stream) : FsWorkbook = + Xlsx.load stream + |> PyWorkbook.toFsWorkbook + + static member fromBytes(bytes: byte []) : FsWorkbook = + Xlsx.read bytes + |> PyWorkbook.toFsWorkbook + + static member toFile(path: string) (wb:FsWorkbook) : unit = + PyWorkbook.fromFsWorkbook wb + |> fun wb -> Xlsx.writeFile(wb,path) + + //static member toStream(stream: System.IO.Stream) (wb:FsWorkbook) : Promise = + // PyWorkbook.fromFsWorkbook wb + // |> fun wb -> Xlsx.writeBuffer(wb,stream) + + static member toBytes(wb:FsWorkbook) : byte [] = + PyWorkbook.fromFsWorkbook wb + |> fun wb -> Xlsx.write(wb) diff --git a/src/FsSpreadsheet/FsWorksheet.fs b/src/FsSpreadsheet/FsWorksheet.fs index c787e99c..c9bcc8a9 100644 --- a/src/FsSpreadsheet/FsWorksheet.fs +++ b/src/FsSpreadsheet/FsWorksheet.fs @@ -150,6 +150,7 @@ type FsWorksheet (name, ?fsRows, ?fsTables, ?fsCellsCollection) = /// /// Returns the FsRow at the given FsRangeAddress. If it does not exist, it is created and appended first. /// + /// The range address of the FsRow. /// If true, the FsRow is created and appended without checking if it already exists. member self.RowWithRange(rangeAddress : FsRangeAddress, ?SkipSearch) = let skipSearch = defaultArg SkipSearch false diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/TestFiles/TestWorkbook_FsSpreadsheet_WRITE.net.xlsx b/tests/FsSpreadsheet.ExcelIO.Tests/TestFiles/TestWorkbook_FsSpreadsheet_WRITE.net.xlsx deleted file mode 100644 index 755e23dc..00000000 Binary files a/tests/FsSpreadsheet.ExcelIO.Tests/TestFiles/TestWorkbook_FsSpreadsheet_WRITE.net.xlsx and /dev/null differ diff --git a/tests/FsSpreadsheet.Exceljs.Tests/Main.fs b/tests/FsSpreadsheet.Exceljs.Tests/Main.fs deleted file mode 100644 index 647a6da2..00000000 --- a/tests/FsSpreadsheet.Exceljs.Tests/Main.fs +++ /dev/null @@ -1,19 +0,0 @@ -module FsSpreadsheet.Exceljs.Tests - -open Fable.Core.JsInterop -open Fable.Mocha -open TestingUtils - -let all = - testList "All" - [ - Workbook.Tests.main - DefaultIO.Tests.main - ] - -[] -let main argv = - #if !FABLE_COMPILER - failwith "The test repo FsSpreadsheet.Exceljs.Tests can only be executed in js environment!" - #endif - Mocha.runTests !!all \ No newline at end of file diff --git a/tests/FsSpreadsheet.Interactive.Tests/FsSpreadsheet.Interactive.Tests.fsproj b/tests/FsSpreadsheet.Interactive.Tests/FsSpreadsheet.Interactive.Tests.fsproj index c811b9c1..5b82c77a 100644 --- a/tests/FsSpreadsheet.Interactive.Tests/FsSpreadsheet.Interactive.Tests.fsproj +++ b/tests/FsSpreadsheet.Interactive.Tests/FsSpreadsheet.Interactive.Tests.fsproj @@ -23,6 +23,6 @@ - + diff --git a/tests/FsSpreadsheet.Exceljs.Tests/DefaultIO.Tests.fs b/tests/FsSpreadsheet.Js.Tests/DefaultIO.Tests.fs similarity index 98% rename from tests/FsSpreadsheet.Exceljs.Tests/DefaultIO.Tests.fs rename to tests/FsSpreadsheet.Js.Tests/DefaultIO.Tests.fs index 6b6ea3bd..0626a179 100644 --- a/tests/FsSpreadsheet.Exceljs.Tests/DefaultIO.Tests.fs +++ b/tests/FsSpreadsheet.Js.Tests/DefaultIO.Tests.fs @@ -2,9 +2,10 @@ open TestingUtils open FsSpreadsheet -open FsSpreadsheet.Exceljs +open FsSpreadsheet.Js open Fable.Core + let private readFromTestFile (testFile: DefaultTestObject.TestFiles) = FsWorkbook.fromXlsxFile(testFile.asRelativePathNode) diff --git a/tests/FsSpreadsheet.Exceljs.Tests/FsSpreadsheet.Exceljs.Tests.csproj b/tests/FsSpreadsheet.Js.Tests/FsSpreadsheet.Js.Tests.fsproj similarity index 69% rename from tests/FsSpreadsheet.Exceljs.Tests/FsSpreadsheet.Exceljs.Tests.csproj rename to tests/FsSpreadsheet.Js.Tests/FsSpreadsheet.Js.Tests.fsproj index 7851ed66..95538507 100644 --- a/tests/FsSpreadsheet.Exceljs.Tests/FsSpreadsheet.Exceljs.Tests.csproj +++ b/tests/FsSpreadsheet.Js.Tests/FsSpreadsheet.Js.Tests.fsproj @@ -12,11 +12,12 @@ - + + - + diff --git a/tests/FsSpreadsheet.Js.Tests/Main.fs b/tests/FsSpreadsheet.Js.Tests/Main.fs new file mode 100644 index 00000000..f2554c42 --- /dev/null +++ b/tests/FsSpreadsheet.Js.Tests/Main.fs @@ -0,0 +1,25 @@ +module FsSpreadsheet.Js.Tests + +open Fable.Core.JsInterop +open Fable.Pyxpecto +open TestingUtils + +let all = + testList "All" + [ + Workbook.Tests.main + DefaultIO.Tests.main + ] + +// This is possibly the most magic used to make this work. +// Js and ts cannot use `Async.RunSynchronously`, instead they use `Async.StartAsPromise`. +// Here we need the transpiler not to worry about the output type. +#if !FABLE_COMPILER_JAVASCRIPT && !FABLE_COMPILER_TYPESCRIPT +let (!!) (any: 'a) = any +#endif +#if FABLE_COMPILER_JAVASCRIPT || FABLE_COMPILER_TYPESCRIPT +open Fable.Core.JsInterop +#endif + +[] +let main argv = !!Pyxpecto.runTests [||] all diff --git a/tests/FsSpreadsheet.Exceljs.Tests/Workbook.Tests.fs b/tests/FsSpreadsheet.Js.Tests/Workbook.Tests.fs similarity index 99% rename from tests/FsSpreadsheet.Exceljs.Tests/Workbook.Tests.fs rename to tests/FsSpreadsheet.Js.Tests/Workbook.Tests.fs index a7e33a52..6cf36b61 100644 --- a/tests/FsSpreadsheet.Exceljs.Tests/Workbook.Tests.fs +++ b/tests/FsSpreadsheet.Js.Tests/Workbook.Tests.fs @@ -2,7 +2,7 @@ module Workbook.Tests open TestingUtils open Fable.ExcelJs -open FsSpreadsheet.Exceljs +open FsSpreadsheet.Js open FsSpreadsheet open Fable.Core diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/DefaultIO.Tests.fs b/tests/FsSpreadsheet.Net.Tests/DefaultIO.Tests.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/DefaultIO.Tests.fs rename to tests/FsSpreadsheet.Net.Tests/DefaultIO.Tests.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/FsSpreadsheet.ExcelIO.Tests.fsproj b/tests/FsSpreadsheet.Net.Tests/FsSpreadsheet.Net.Tests.fsproj similarity index 87% rename from tests/FsSpreadsheet.ExcelIO.Tests/FsSpreadsheet.ExcelIO.Tests.fsproj rename to tests/FsSpreadsheet.Net.Tests/FsSpreadsheet.Net.Tests.fsproj index 4dce63d4..ddb13f7d 100644 --- a/tests/FsSpreadsheet.ExcelIO.Tests/FsSpreadsheet.ExcelIO.Tests.fsproj +++ b/tests/FsSpreadsheet.Net.Tests/FsSpreadsheet.Net.Tests.fsproj @@ -22,7 +22,7 @@ - + @@ -33,7 +33,7 @@ - + \ No newline at end of file diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/FsWorkbook.fs b/tests/FsSpreadsheet.Net.Tests/FsWorkbook.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/FsWorkbook.fs rename to tests/FsSpreadsheet.Net.Tests/FsWorkbook.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/Main.fs b/tests/FsSpreadsheet.Net.Tests/Main.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/Main.fs rename to tests/FsSpreadsheet.Net.Tests/Main.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/Cell.fs b/tests/FsSpreadsheet.Net.Tests/OpenXml/Cell.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/Cell.fs rename to tests/FsSpreadsheet.Net.Tests/OpenXml/Cell.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/FsExtensions.fs b/tests/FsSpreadsheet.Net.Tests/OpenXml/FsExtensions.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/FsExtensions.fs rename to tests/FsSpreadsheet.Net.Tests/OpenXml/FsExtensions.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/Sheet.fs b/tests/FsSpreadsheet.Net.Tests/OpenXml/Sheet.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/Sheet.fs rename to tests/FsSpreadsheet.Net.Tests/OpenXml/Sheet.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/Spreadsheet.fs b/tests/FsSpreadsheet.Net.Tests/OpenXml/Spreadsheet.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/Spreadsheet.fs rename to tests/FsSpreadsheet.Net.Tests/OpenXml/Spreadsheet.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/Workbook.fs b/tests/FsSpreadsheet.Net.Tests/OpenXml/Workbook.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/OpenXml/Workbook.fs rename to tests/FsSpreadsheet.Net.Tests/OpenXml/Workbook.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/Stylesheet.Tests.fs b/tests/FsSpreadsheet.Net.Tests/Stylesheet.Tests.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/Stylesheet.Tests.fs rename to tests/FsSpreadsheet.Net.Tests/Stylesheet.Tests.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/Table.fs b/tests/FsSpreadsheet.Net.Tests/Table.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/Table.fs rename to tests/FsSpreadsheet.Net.Tests/Table.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/TestFiles/README.md b/tests/FsSpreadsheet.Net.Tests/TestFiles/README.md similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/TestFiles/README.md rename to tests/FsSpreadsheet.Net.Tests/TestFiles/README.md diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/TestObjects.fs b/tests/FsSpreadsheet.Net.Tests/TestObjects.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/TestObjects.fs rename to tests/FsSpreadsheet.Net.Tests/TestObjects.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/ZipArchiveReader.fs b/tests/FsSpreadsheet.Net.Tests/ZipArchiveReader.fs similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/ZipArchiveReader.fs rename to tests/FsSpreadsheet.Net.Tests/ZipArchiveReader.fs diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/data/2EXT02_Protein.xlsx b/tests/FsSpreadsheet.Net.Tests/data/2EXT02_Protein.xlsx similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/data/2EXT02_Protein.xlsx rename to tests/FsSpreadsheet.Net.Tests/data/2EXT02_Protein.xlsx diff --git a/tests/FsSpreadsheet.ExcelIO.Tests/data/testUnit.xlsx b/tests/FsSpreadsheet.Net.Tests/data/testUnit.xlsx similarity index 100% rename from tests/FsSpreadsheet.ExcelIO.Tests/data/testUnit.xlsx rename to tests/FsSpreadsheet.Net.Tests/data/testUnit.xlsx diff --git a/tests/FsSpreadsheet.Py.Tests/Cell.fs b/tests/FsSpreadsheet.Py.Tests/Cell.fs new file mode 100644 index 00000000..155e5db6 --- /dev/null +++ b/tests/FsSpreadsheet.Py.Tests/Cell.fs @@ -0,0 +1,28 @@ +module Cell.Tests + +open TestingUtils +open Fable.Openpyxl +open FsSpreadsheet.ExcelPy +open FsSpreadsheet + +open Fable.Core + +let fromFsCell = testList "fromFsCell" [ + testCase "Boolean" <| fun _ -> + let fsCell = FsCell(true, DataType.Boolean) + let pyCell = PyCell.fromFsCell fsCell + let expected = Some(box true) + Expect.equal pyCell expected "" +] + +//let toFsCell = testList "toFsCell" [ +// testCase "Boolean" <| fun _ -> +// let pyCell = + +//] + + +let main = testList "Cell" [ + //toFsCell + fromFsCell +] diff --git a/tests/FsSpreadsheet.Py.Tests/DefaultIO.Tests.fs b/tests/FsSpreadsheet.Py.Tests/DefaultIO.Tests.fs new file mode 100644 index 00000000..d8a2c653 --- /dev/null +++ b/tests/FsSpreadsheet.Py.Tests/DefaultIO.Tests.fs @@ -0,0 +1,53 @@ +module DefaultIO.Tests + +open TestingUtils +open FsSpreadsheet +open FsSpreadsheet.ExcelPy +open Fable.Openpyxl + + +let private readFromTestFile (testFile: DefaultTestObject.TestFiles) = + FsWorkbook.fromXlsxFile(testFile.asRelativePathNode) + +let private tests_Read = testList "Read" [ + + testCase "Excel" <| fun _ -> + let wb = readFromTestFile DefaultTestObject.TestFiles.Excel + Expect.isDefaultTestObject wb + + testCase "Libre" <| fun _ -> + let wb = readFromTestFile DefaultTestObject.TestFiles.Libre + Expect.isDefaultTestObject wb + + testCase "FableExceljs" <| fun _ -> + let wb = readFromTestFile DefaultTestObject.TestFiles.FableExceljs + Expect.isDefaultTestObject wb + + testCase "ClosedXML" <| fun _ -> + let wb = readFromTestFile DefaultTestObject.TestFiles.ClosedXML + Expect.isDefaultTestObject wb + + testCase "FsSpreadsheetNET" <| fun _ -> + let wb = readFromTestFile DefaultTestObject.TestFiles.FsSpreadsheetNET + Expect.isDefaultTestObject wb + + testCase "FsSpreadsheetJS" <| fun _ -> + let wb = readFromTestFile DefaultTestObject.TestFiles.FsSpreadsheetJS + Expect.isDefaultTestObject wb + +] + +let private tests_Write = testList "Write" [ + testCase "default" <| fun _ -> + let wb = DefaultTestObject.defaultTestObject() + let p = DefaultTestObject.WriteTestFiles.FsSpreadsheetPY.asRelativePathNode + do FsWorkbook.toFile p wb + let wb_read = FsWorkbook.fromXlsxFile p + Expect.isDefaultTestObject wb_read + +] + +let main = testList "DefaultIO" [ + tests_Read + tests_Write +] \ No newline at end of file diff --git a/tests/FsSpreadsheet.Exceljs.Tests/FsSpreadsheet.Exceljs.Tests.fsproj b/tests/FsSpreadsheet.Py.Tests/FsSpreadsheet.Py.Tests.fsproj similarity index 59% rename from tests/FsSpreadsheet.Exceljs.Tests/FsSpreadsheet.Exceljs.Tests.fsproj rename to tests/FsSpreadsheet.Py.Tests/FsSpreadsheet.Py.Tests.fsproj index 7851ed66..a96bc3e3 100644 --- a/tests/FsSpreadsheet.Exceljs.Tests/FsSpreadsheet.Exceljs.Tests.fsproj +++ b/tests/FsSpreadsheet.Py.Tests/FsSpreadsheet.Py.Tests.fsproj @@ -7,16 +7,20 @@ - + + + + - + + - + diff --git a/tests/FsSpreadsheet.Py.Tests/Main.fs b/tests/FsSpreadsheet.Py.Tests/Main.fs new file mode 100644 index 00000000..1fd019ae --- /dev/null +++ b/tests/FsSpreadsheet.Py.Tests/Main.fs @@ -0,0 +1,27 @@ +module FsSpreadsheet.ExcelPy.Tests + +open Fable.Pyxpecto +open TestingUtils + +let all = + testList "All" + [ + Cell.Tests.main + Table.Tests.main + Worksheet.Tests.main + Workbook.Tests.main + DefaultIO.Tests.main + ] + +//// This is possibly the most magic used to make this work. +//// Js and ts cannot use `Async.RunSynchronously`, instead they use `Async.StartAsPromise`. +//// Here we need the transpiler not to worry about the output type. +//#if !FABLE_COMPILER_JAVASCRIPT && !FABLE_COMPILER_TYPESCRIPT +//let (!!) (any: 'a) = any +//#endif +//#if FABLE_COMPILER_JAVASCRIPT || FABLE_COMPILER_TYPESCRIPT +//open Fable.Core.JsInterop +//#endif + +[] +let main argv = Pyxpecto.runTests [||] all diff --git a/tests/FsSpreadsheet.Py.Tests/Table.fs b/tests/FsSpreadsheet.Py.Tests/Table.fs new file mode 100644 index 00000000..10b74fb0 --- /dev/null +++ b/tests/FsSpreadsheet.Py.Tests/Table.fs @@ -0,0 +1,37 @@ +module Table.Tests + +open TestingUtils +open Fable.Openpyxl +open FsSpreadsheet.ExcelPy +open FsSpreadsheet + +open Fable.Core.PyInterop +open Fable.Core + +let fromFsTable = testList "fromFsTable" [ + testCase "Table" <| fun _ -> + let rangeString = "A1:E5" + let fsTable = FsTable("MyTable", FsRangeAddress(rangeString)) + let pyTable = PyTable.fromFsTable fsTable + let expected = Table.create("MyTable", rangeString) + + Expect.equal pyTable.name expected.name "" + Expect.equal pyTable.displayName expected.displayName "" + Expect.equal pyTable?ref expected?ref "" + Expect.equal pyTable?ref rangeString "" +] + +let toFsTable = testList "toFsTable" [ + testCase "Table" <| fun _ -> + let pyTable = Table.create("MyTable", "A1:E5") + let fsTable = PyTable.toFsTable pyTable + let expected = FsTable("MyTable", FsRangeAddress("A1:E5")) + Expect.equal fsTable.Name expected.Name "" + Expect.equal fsTable.RangeAddress.Range expected.RangeAddress.Range "" + +] + +let main = testList "Table" [ + fromFsTable + toFsTable +] \ No newline at end of file diff --git a/tests/FsSpreadsheet.Py.Tests/Workbook.Tests.fs b/tests/FsSpreadsheet.Py.Tests/Workbook.Tests.fs new file mode 100644 index 00000000..41d7fb9b --- /dev/null +++ b/tests/FsSpreadsheet.Py.Tests/Workbook.Tests.fs @@ -0,0 +1,298 @@ +module Workbook.Tests + +open TestingUtils +open Fable.Openpyxl +open FsSpreadsheet.ExcelPy +open FsSpreadsheet + +open Fable.Core.PyInterop +open Fable.Core +open Fable.Pyxpecto + +let private tests_toFsWorkbook = testList "toFsWorkbook" [ + testCase "empty" <| fun _ -> + let pyWB = Workbook.create() + let fsWB = PyWorkbook.toFsWorkbook pyWB + + Expect.equal (fsWB.GetWorksheets().Count) 0 "both no worksheet" + //testCase "worksheet" <| fun _ -> + // let jswb = exceljs.excel.workbook() + // let _ = jswb.addworksheet("my awesome worksheet") + // expect.passwithmsg "create jswb" + // let fswb = jsworkbook.readtofsworkbook jswb + // expect.passwithmsg "convert to fswb" + // let jswslist = jswb.worksheets + // let fswslist = fswb.getworksheets() + // expect.equal fswslist.count jswslist.length "both 1 worksheet" + // expect.equal fswslist.[0].name "my awesome worksheet" "correct worksheet name" + //testCase "worksheets" <| fun _ -> + // let jswb = exceljs.excel.workbook() + // let _ = jswb.addworksheet("my awesome worksheet") + // let _ = jswb.addworksheet("my best worksheet") + // let _ = jswb.addworksheet("my nice worksheet") + // expect.passwithmsg "create jswb" + // let fswb = jsworkbook.readtofsworkbook jswb + // expect.passwithmsg "convert to fswb" + // let jswslist = jswb.worksheets + // let fswslist = fswb.getworksheets() + // expect.equal fswslist.count jswslist.length "both 3 worksheets" + // let testws (index:int) = + // let fsws = fswslist.item index + // let jsws = jswslist.[index] + // expect.equal fsws.name jsws.name $"correct worksheet name for index {index}." + // for i in 0 .. (jswb.worksheets.length-1) do + // testws i + //testCase "table, no body" <| fun _ -> + // let jswb = exceljs.excel.workbook() + // let jsws = jswb.addworksheet("my awesome worksheet") + // let tablecolumns = [|tablecolumn("column 1 nice"); tablecolumn("column 2 cool")|] + // let table = table("my_awesome_table", "b1", tablecolumns, [||]) + // let _ = jsws.addtable(table) + // expect.passwithmsg "create jswb" + // let fswb = jsworkbook.readtofsworkbook jswb + // expect.passwithmsg "convert to fswb" + // let fstables_a = fswb.getworksheets().[0].tables + // let fstables_b = fswb.gettables() + // expect.haslength (jsws.gettables()) 1 "js table count" + // expect.haslength fstables_a 1 "fs table count (a)" + // expect.haslength fstables_b 1 "fs table count (b)" + // expect.equal fstables_a.[0].name "my_awesome_table" "table name" + // let fstable = fstables_a.[0] + // expect.istrue (fstable.showheaderrow) "show header row" + // expect.equal (fstable.rangeaddress.range) ("b1:c1") "rangeaddress" + // let getcellvalue (address: string) = + // let ws = fswb.getworksheetat 1 + // let range = fsaddress(address) + // ws.getcellat(range.rownumber, range.columnnumber).value + // //fstable.cell(fsaddress(address), (fswb.getworksheetat 1).cellcollection).value //bugged in fsspreadsheet v3.1.1 + // expect.equal (getcellvalue "b1") "column 1 nice" "b1" + // expect.equal (getcellvalue "c1") "column 2 cool" "c1" + + //testCase "table, with body" <| fun _ -> + // let jswb = exceljs.excel.workbook() + // let jsws = jswb.addworksheet("my awesome worksheet") + // let tablecolumns = [|tablecolumn("column 1 nice"); tablecolumn("column 2 cool"); tablecolumn("column 3 wow")|] + // let rows = [| + // [| box "test"; box 2; box true|] + // [| box "test2"; box 20; box false|] + // |] + // let table = table("my_awesome_table", "b1", tablecolumns, rows) + // let _ = jsws.addtable(table) + // expect.passwithmsg "create jswb" + // let fswb = jsworkbook.readtofsworkbook jswb + // expect.passwithmsg "convert to fswb" + // let fstables = fswb.gettables() + // expect.haslength (jsws.gettables()) 1 "js table count" + // expect.haslength fstables 1 "fs table count " + // let fstable = fstables.[0] + // expect.equal fstable.name "my_awesome_table" "table name" + // expect.istrue (fstable.showheaderrow) "show header row" + // expect.equal (fstable.rangeaddress.range) ("b1:d3") "rangeaddress" + //testCase "table, with body, check cells" <| fun _ -> + // let jswb = exceljs.excel.workbook() + // let jsws = jswb.addworksheet("my awesome worksheet") + // let tablecolumns = [|tablecolumn("column 1 nice"); tablecolumn("column 2 cool"); tablecolumn("column 3 wow")|] + // let rows = [| + // [| box "test"; box 2; box true|] + // [| box "test2"; box 20; box false|] + // |] + // let table = table("my_awesome_table", "b1", tablecolumns, rows) + // let _ = jsws.addtable(table) + // expect.passwithmsg "create jswb" + // let fswb = jsworkbook.readtofsworkbook jswb + // let getcellvalue (address: string) = + // let ws = fswb.getworksheetat 1 + // let range = fsaddress(address) + // ws.getcellat(range.rownumber, range.columnnumber) + // //fstable.cell(fsaddress(address), (fswb.getworksheetat 1).cellcollection).value //bugged in fsspreadsheet v3.1.1 + // let inline expectcellvalue (address: string) (getas: fscell -> 'a) (expectedvalue: 'a) = + // let c = getcellvalue address + // let a = getas c + // expect.equal a expectedvalue address + // expectcellvalue "b1" (fun c -> c.value) "column 1 nice" + // expectcellvalue "b2" (fun c -> c.value) "test" + // expectcellvalue "b3" (fun c -> c.value) "test2" + // expectcellvalue "c1" (fun c -> c.value) "column 2 cool" + // expectcellvalue "c2" (fun c -> c.valueasint()) 2 + // expectcellvalue "c3" (fun c -> c.valueasint()) 20 + // expectcellvalue "d1" (fun c -> c.value) "column 3 wow" + // expectcellvalue "d2" (fun c -> c.valueasbool()) true + // expectcellvalue "d3" (fun c -> c.valueasbool()) false +] + +let tests_toPyWorkbook = testList "toPyWorkbook" [ + testCase "empty" <| fun _ -> + + let fsWB = new FsWorkbook() + Expect.fails (fun () -> PyWorkbook.fromFsWorkbook fsWB |> ignore) "no worksheet given" + testCase "worksheet" <| fun _ -> + let fsWB = new FsWorkbook() + let _ = fsWB.InitWorksheet("my awesome worksheet") + let pyWB = PyWorkbook.fromFsWorkbook fsWB + Expect.passWithMsg "convert to jswb" + let pyWsList = pyWB?worksheets + Expect.equal (pyWsList |> Array.length) 1 "worksheet count" + //pyWB?worksheets + //|> List.map (fun (ws : FsWorksheet) -> ws.Name = "my awesome worksheet") + + + //testCase "worksheets" <| fun _ -> + // let fswb = new fsworkbook() + // let _ = fswb.initworksheet("my awesome worksheet") + // let _ = fswb.initworksheet("my cool worksheet") + // let _ = fswb.initworksheet("my wow worksheet") + // expect.passwithmsg "create fswb" + // let jswb = jsworkbook.writefromfsworkbook fswb + // expect.passwithmsg "convert to jswb" + // let fswslist = fswb.getworksheets() + // let jswslist = jswb.worksheets + // expect.equal fswslist.count jswslist.length "both no worksheet" + // expect.haslength jswslist 3 "worksheet count" + // expect.equal jswslist.[0].name "my awesome worksheet" "1 worksheet name" + // expect.equal jswslist.[1].name "my cool worksheet" "2 worksheet name" + // expect.equal jswslist.[2].name "my wow worksheet" "3 worksheet name" + //testCase "table, no body" <| fun _ -> + // let fswb = new fsworkbook() + // let fsws = fswb.initworksheet("my awesome worksheet") + // let _ = fsws.addcell(fscell("my column 1",address=fsaddress("b1"))) + // let _ = fsws.addcell(fscell("my column 2",address=fsaddress("c1"))) + // let t = fstable("my_new_table", fsrangeaddress("b1:c1")) + // let _ = fsws.addtable(t) + // expect.passwithmsg "create jswb" + // let jswb = jsworkbook.writefromfsworkbook fswb + // expect.passwithmsg "convert to fswb" + // let jsws = jswb.worksheets.[0] + // expect.equal jsws.name "my awesome worksheet" "ws name" + // let jstables = jsws.gettables() + // expect.haslength jstables 1 "table count" + // let jstableref = jstables.[0] + // expect.equal jstableref.name "my_new_table" "table name" + // let jstable = jstables.[0].table.value + // expect.haslength jstable.rows 0 "table body is 0" + // expect.equal jstable.columns.[0].name "my column 1" "my column 1" + // expect.equal jstable.columns.[1].name "my column 2" "my column 2" + //testCase "table, with body" <| fun _ -> + // let fswb = new fsworkbook() + // let fsws = fswb.initworksheet("my awesome worksheet") + // let _ = fsws.addcell(fscell("my column 1",address=fsaddress("b1"))) + // let _ = fsws.addcell(fscell(2,address=fsaddress("b2"))) + // let _ = fsws.addcell(fscell(20,address=fsaddress("b3"))) + // let _ = fsws.addcell(fscell("my column 2",address=fsaddress("c1"))) + // let _ = fsws.addcell(fscell("row2",address=fsaddress("c2"))) + // let _ = fsws.addcell(fscell("row20",address=fsaddress("c3"))) + // let _ = fsws.addcell(fscell("my column 3",address=fsaddress("d1"))) + // let _ = fsws.addcell(fscell(true,address=fsaddress("d2"))) + // let _ = fsws.addcell(fscell(false,address=fsaddress("d3"))) + // let t = fstable("my_new_table", fsrangeaddress("b1:d3")) + // let _ = fsws.addtable(t) + // expect.passwithmsg "create jswb" + // let jswb = jsworkbook.writefromfsworkbook fswb + // expect.passwithmsg "convert to fswb" + // let jsws = jswb.worksheets.[0] + // expect.equal jsws.name "my awesome worksheet" "ws name" + // let jstables = jsws.gettables() + // expect.haslength jstables 1 "table count" + // let jstableref = jstables.[0] + // expect.equal jstableref.name "my_new_table" "table name" + // let jstable = jstables.[0].table.value + // expect.equal jstable.columns.[0].name "my column 1" "my column 1" + // expect.equal jstable.columns.[1].name "my column 2" "my column 2" + // expect.equal jstable.columns.[2].name "my column 3" "my column 3" + // expect.haslength jstable.rows 2 "table body has 2 rows" + //testCase "table, with body, check cells" <| fun _ -> + // let fswb = new fsworkbook() + // let fsws = fswb.initworksheet("my awesome worksheet") + // let _ = fsws.addcell(fscell("my column 1",address=fsaddress("b1"))) + // let _ = fsws.addcell(fscell(2,datatype.number,address=fsaddress("b2"))) + // let _ = fsws.addcell(fscell(20,datatype.number,address=fsaddress("b3"))) + // let _ = fsws.addcell(fscell("my column 2",address=fsaddress("c1"))) + // let _ = fsws.addcell(fscell("row2",address=fsaddress("c2"))) + // let _ = fsws.addcell(fscell("row20",address=fsaddress("c3"))) + // let _ = fsws.addcell(fscell("my column 3",address=fsaddress("d1"))) + // let _ = fsws.addcell(fscell(true, datatype.boolean, address=fsaddress("d2"))) + // let _ = fsws.addcell(fscell(false, datatype.boolean, address=fsaddress("d3"))) + // let t = fstable("my_new_table", fsrangeaddress("b1:d3")) + // let _ = fsws.addtable(t) + // fsws.rescanrows() + // expect.passwithmsg "create jswb" + // let jswb = jsworkbook.writefromfsworkbook fswb + // let jstable = jswb.worksheets.[0].gettables().[0].table.value + // let row0 = jstable.rows.[0] + // let row1 = jstable.rows.[1] + // expect.haslength row0 3 "row b2:d2 length" + // expect.haslength row1 3 "row b3:d3 length" + // expect.equal row0.[0] 2 "b2" + // expect.equal row1.[0] 20 "b3" + // expect.equal row0.[1] "row2" "c2" + // expect.equal row1.[1] "row20" "c3" + // expect.equal row0.[2] true "d2" + // expect.equal row1.[2] false "d3" + //testCase "table columncount()" <| fun _ -> + // let fswb = new fsworkbook() + // let fsws = fswb.initworksheet("my awesome worksheet") + // let _ = fsws.addcell(fscell("my column 1",address=fsaddress("b1"))) + // let _ = fsws.addcell(fscell(2,datatype.number,address=fsaddress("b2"))) + // let _ = fsws.addcell(fscell(20,datatype.number,address=fsaddress("b3"))) + // let _ = fsws.addcell(fscell("my column 2",address=fsaddress("c1"))) + // let _ = fsws.addcell(fscell("row2",address=fsaddress("c2"))) + // let _ = fsws.addcell(fscell("row20",address=fsaddress("c3"))) + // let _ = fsws.addcell(fscell("my column 3",address=fsaddress("d1"))) + // let _ = fsws.addcell(fscell(true, datatype.boolean, address=fsaddress("d2"))) + // let _ = fsws.addcell(fscell(false, datatype.boolean, address=fsaddress("d3"))) + // let t = fstable("my_new_table", fsrangeaddress("b1:d3")) + // let _ = fsws.addtable(t) + // fsws.rescanrows() + // let table = fsws.tables.[0] + // expect.equal (table.columncount()) 3 "column count" + //testCase "table with implicit set" <| fun _ -> + // let fswb = new fsworkbook() + // let fsws = fswb.initworksheet("my awesome worksheet") + // fsws.row(1).[2].setvalueas "my column 1" + // fsws.row(2).[2].setvalueas 2 + // fsws.row(3).[2].setvalueas 20 + // fsws.row(1).[3].setvalueas "my column 2" + // fsws.row(2).[3].setvalueas "row2" + // fsws.row(3).[3].setvalueas "row20" + // fsws.row(1).[4].setvalueas "my column 2" + // fsws.row(2).[4].setvalueas true + // fsws.row(3).[4].setvalueas false + // let t = fstable("my new table", fsrangeaddress("b1:d3")) + // let _ = fsws.addtable(t) + // fsws.rescanrows() + // let table = fsws.tables.[0] + // expect.equal (table.columncount()) 3 "column count" +] + +//open fable.core + +//let tests_xlsx = testList "xlsx" [ +// testList "read" [ +// testCaseasync "isa.assay.xlsx" <| async { +// let! fswb = xlsx.fromxlsxfile("./tests/js/testfiles/isa.assay.xlsx") |> async.awaitpromise +// expect.equal (fswb.getworksheets().count) 5 "count" +// } +// ] +//] + +//let performance = +// testList "performace" [ +// testCaseasync "readbigfile" <| async { +// let sw = stopwatch() +// let p = defaulttestobject.bigfile.asrelativepathnode +// sw.start() +// let! wb = fsworkbook.fromxlsxfile(p) |> async.awaitpromise +// sw.stop() +// let ms = sw.elapsed.milliseconds +// expect.istrue (ms < 2000) $"elapsed time should be less than 2000ms but was {ms}ms" +// expect.equal (wb.getworksheetat(1).rows.count) 153991 "row count should be 153991" +// } +// ] + + +let main = testList "Workbook" [ + tests_toFsWorkbook + tests_toPyWorkbook + //tests_xlsx + //performance +] + diff --git a/tests/FsSpreadsheet.Py.Tests/Worksheet.Tests.fs b/tests/FsSpreadsheet.Py.Tests/Worksheet.Tests.fs new file mode 100644 index 00000000..4c65b3ba --- /dev/null +++ b/tests/FsSpreadsheet.Py.Tests/Worksheet.Tests.fs @@ -0,0 +1,47 @@ +module Worksheet.Tests + +open TestingUtils +open FsSpreadsheet.ExcelPy +open FsSpreadsheet +open Fable.Openpyxl +open Fable.Core.PyInterop +open Fable.Core + +let wsName = "MySheet" + +let fromFsWorksheet = testList "fromFsWorksheet" [ + testCase "Empty" <| fun _ -> + let wb = Workbook.create() + let fsWS = FsWorksheet(wsName) + let pyWS = PyWorksheet.fromFsWorksheet wb fsWS + + Expect.equal pyWS.title wsName "Name did not match" + Expect.equal pyWS.values.Length 0 "Values did not match" + testCase "Simple" <| fun _ -> + let wb = Workbook.create() + let fsWS = FsWorksheet(wsName) + let cell = FsCell("Hello", address = FsAddress("A1")) + fsWS.AddCell(cell) |> ignore + let pyWS = PyWorksheet.fromFsWorksheet wb fsWS + + let expectedCells = [| [| box "Hello" |] |] + + Expect.equal pyWS.title wsName "Name did not match" + Expect.equal pyWS.values expectedCells "Values did not match" +] + + +let toFsWorksheet = testList "toFsWorksheet" [ + testCase "Empty" <| fun _ -> + let wb = Workbook.create() + let pyWS = wb.create_sheet(wsName) + let fsWS = PyWorksheet.toFsWorksheet pyWS + Expect.equal fsWS.Name wsName "Name did not match" + Expect.equal (fsWS.CellCollection.GetCells() |> Seq.length) 0 "Cells did not match" + +] + +let main = testList "Worksheet" [ + fromFsWorksheet + toFsWorksheet +] \ No newline at end of file diff --git a/tests/FsSpreadsheet.Tests/DSL/CellBuilderTests.fs b/tests/FsSpreadsheet.Tests/DSL/CellBuilderTests.fs index f327d279..b55f5e38 100644 --- a/tests/FsSpreadsheet.Tests/DSL/CellBuilderTests.fs +++ b/tests/FsSpreadsheet.Tests/DSL/CellBuilderTests.fs @@ -1,11 +1,8 @@ module DSL.CellBuilder -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto + open FsSpreadsheet open FsSpreadsheet.DSL diff --git a/tests/FsSpreadsheet.Tests/FsAddressTests.fs b/tests/FsSpreadsheet.Tests/FsAddressTests.fs index d32346de..f91d3931 100644 --- a/tests/FsSpreadsheet.Tests/FsAddressTests.fs +++ b/tests/FsSpreadsheet.Tests/FsAddressTests.fs @@ -1,10 +1,6 @@ module FsAddress -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto open FsSpreadsheet diff --git a/tests/FsSpreadsheet.Tests/FsCellTests.fs b/tests/FsSpreadsheet.Tests/FsCellTests.fs index 73261c44..8e1a80cc 100644 --- a/tests/FsSpreadsheet.Tests/FsCellTests.fs +++ b/tests/FsSpreadsheet.Tests/FsCellTests.fs @@ -1,11 +1,7 @@ module FsCell -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif open FsSpreadsheet +open Fable.Pyxpecto let dataType = testList "DataType" [ @@ -54,8 +50,8 @@ let dataType = testList "InferCellValue byte = 255uy" [ let byteValTest = 255uy let resultDtTest, resultBytTest = DataType.InferCellValue byteValTest - testCase "Correct DataType" <| fun _ -> - Expect.isTrue (resultDtTest = DataType.Number) "is not the expected DataType.Number" + ptestCase "Correct DataType" <| fun _ -> + Expect.equal resultDtTest DataType.Number "is not the expected DataType.Number" testCase "Correct value" <| fun _ -> Expect.equal (box byteValTest) resultBytTest "resulting value is not correct" ] diff --git a/tests/FsSpreadsheet.Tests/FsCellsCollectionTests.fs b/tests/FsSpreadsheet.Tests/FsCellsCollectionTests.fs index a773382e..0a804574 100644 --- a/tests/FsSpreadsheet.Tests/FsCellsCollectionTests.fs +++ b/tests/FsSpreadsheet.Tests/FsCellsCollectionTests.fs @@ -1,10 +1,6 @@ module FsCellsCollection -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto open FsSpreadsheet let dummyFsCells = diff --git a/tests/FsSpreadsheet.Tests/FsColumnTests.fs b/tests/FsSpreadsheet.Tests/FsColumnTests.fs index 69ed712d..1849c89b 100644 --- a/tests/FsSpreadsheet.Tests/FsColumnTests.fs +++ b/tests/FsSpreadsheet.Tests/FsColumnTests.fs @@ -1,10 +1,6 @@ module FsColumn -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto open FsSpreadsheet let getDummyWorkSheet() = diff --git a/tests/FsSpreadsheet.Tests/FsRowTests.fs b/tests/FsSpreadsheet.Tests/FsRowTests.fs index 05a94aa4..09fffd35 100644 --- a/tests/FsSpreadsheet.Tests/FsRowTests.fs +++ b/tests/FsSpreadsheet.Tests/FsRowTests.fs @@ -1,11 +1,8 @@ module FsRow open TestingUtils -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto + open FsSpreadsheet @@ -20,7 +17,7 @@ let getDummyWorkSheet() = let performace = testList "performance" [ - testCase "FrowFromRange-SkipSearch" (fun () -> + ptestCase "FrowFromRange-SkipSearch" (fun () -> let rowCount= 100000 let ws = FsWorksheet.init("MyWorksheet") let timer = Stopwatch() diff --git a/tests/FsSpreadsheet.Tests/FsSpreadsheet.Tests.fsproj b/tests/FsSpreadsheet.Tests/FsSpreadsheet.Tests.fsproj index d07df6d7..74414d53 100644 --- a/tests/FsSpreadsheet.Tests/FsSpreadsheet.Tests.fsproj +++ b/tests/FsSpreadsheet.Tests/FsSpreadsheet.Tests.fsproj @@ -23,8 +23,7 @@ - - + @@ -35,7 +34,7 @@ - + diff --git a/tests/FsSpreadsheet.Tests/FsTableFieldTests.fs b/tests/FsSpreadsheet.Tests/FsTableFieldTests.fs index 4603db4f..70e80f8c 100644 --- a/tests/FsSpreadsheet.Tests/FsTableFieldTests.fs +++ b/tests/FsSpreadsheet.Tests/FsTableFieldTests.fs @@ -1,11 +1,7 @@ module FsTableField open FsSpreadsheet -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto let dummyFsRangeAddress = FsRangeAddress("C1:C3") let dummyFsRangeColumn = FsRangeColumn(dummyFsRangeAddress) diff --git a/tests/FsSpreadsheet.Tests/FsTableTests.fs b/tests/FsSpreadsheet.Tests/FsTableTests.fs index 79a5bc40..242e1583 100644 --- a/tests/FsSpreadsheet.Tests/FsTableTests.fs +++ b/tests/FsSpreadsheet.Tests/FsTableTests.fs @@ -1,10 +1,6 @@ module FsTable -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto open FsSpreadsheet let dummyFsCells = diff --git a/tests/FsSpreadsheet.Tests/FsWorkbookTests.fs b/tests/FsSpreadsheet.Tests/FsWorkbookTests.fs index ebb3f462..5d42c4c6 100644 --- a/tests/FsSpreadsheet.Tests/FsWorkbookTests.fs +++ b/tests/FsSpreadsheet.Tests/FsWorkbookTests.fs @@ -1,10 +1,6 @@ module FsWorkbook -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto open FsSpreadsheet diff --git a/tests/FsSpreadsheet.Tests/FsWorksheetTests.fs b/tests/FsSpreadsheet.Tests/FsWorksheetTests.fs index 0e8c7400..7465adce 100644 --- a/tests/FsSpreadsheet.Tests/FsWorksheetTests.fs +++ b/tests/FsSpreadsheet.Tests/FsWorksheetTests.fs @@ -1,10 +1,7 @@ module FsWorkSheet -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto + open FsSpreadsheet let dummyCellsColl = FsCellsCollection() diff --git a/tests/FsSpreadsheet.Tests/Main.fs b/tests/FsSpreadsheet.Tests/Main.fs index 309e43a6..91f490d7 100644 --- a/tests/FsSpreadsheet.Tests/Main.fs +++ b/tests/FsSpreadsheet.Tests/Main.fs @@ -1,11 +1,9 @@ module FsSpreadsheet.Tests -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -[] -#endif +open Fable.Pyxpecto + + + let all = testList "All" [ @@ -18,20 +16,18 @@ let all = FsCellsCollection.main FsCell.main FsAddress.main - DSL.CellBuilder.main ] -[] -let main argv = - #if FABLE_COMPILER - Mocha.runTests all - #else - Tests.runTestsWithCLIArgs [] argv all - #endif +// This is possibly the most magic used to make this work. +// Js and ts cannot use `Async.RunSynchronously`, instead they use `Async.StartAsPromise`. +// Here we need the transpiler not to worry about the output type. +#if !FABLE_COMPILER_JAVASCRIPT && !FABLE_COMPILER_TYPESCRIPT +let (!!) (any: 'a) = any +#endif +#if FABLE_COMPILER_JAVASCRIPT || FABLE_COMPILER_TYPESCRIPT +open Fable.Core.JsInterop +#endif -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif \ No newline at end of file +[] +let main argv = !!Pyxpecto.runTests [||] all diff --git a/tests/FsSpreadsheet.Tests/Utils.fs b/tests/FsSpreadsheet.Tests/Utils.fs index 69e8d4c4..8cd6c604 100644 --- a/tests/FsSpreadsheet.Tests/Utils.fs +++ b/tests/FsSpreadsheet.Tests/Utils.fs @@ -9,11 +9,8 @@ module Helpers = Seq.mapi2 (fun i s p -> i,s,p) s1 s2 |> Seq.find (function |_,Some s,Some p when s=p -> false |_-> true) -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto + module Expect = diff --git a/tests/JS/Exceljs.js b/tests/JS/Exceljs.js index 3463ef35..5f0e0330 100644 --- a/tests/JS/Exceljs.js +++ b/tests/JS/Exceljs.js @@ -1,11 +1,11 @@ import { equal } from 'assert'; -import { Xlsx } from './FsSpreadsheet.Exceljs/Xlsx.js'; -import { FsWorkbook } from "./FsSpreadsheet.Exceljs/FsSpreadsheet/FsWorkbook.js"; -import { FsRangeAddress_$ctor_Z721C83C5, FsRangeAddress__get_Range } from "./FsSpreadsheet.Exceljs/FsSpreadsheet/Ranges/FsRangeAddress.js"; -import { FsTable } from "./FsSpreadsheet.Exceljs/FsSpreadsheet/Tables/FsTable.js"; -import { writeFromFsWorkbook, readToFsWorkbook } from "./FsSpreadsheet.Exceljs/Workbook.js"; +import { Xlsx } from './FsSpreadsheet.Js/Xlsx.js'; +import { FsWorkbook } from "./FsSpreadsheet.Js/FsSpreadsheet/FsWorkbook.js"; +import { FsRangeAddress_$ctor_Z721C83C5, FsRangeAddress__get_Range } from "./FsSpreadsheet.Js/FsSpreadsheet/Ranges/FsRangeAddress.js"; +import { FsTable } from "./FsSpreadsheet.Js/FsSpreadsheet/Tables/FsTable.js"; +import { writeFromFsWorkbook, readToFsWorkbook } from "./FsSpreadsheet.Js/Workbook.js"; -describe('FsSpreadsheet.Exceljs', function () { +describe('FsSpreadsheet.Js', function () { describe('read', function () { it('values', async () => { const path = "tests/JS/TestFiles/ReadTable.xlsx"; // path always from package.json diff --git a/tests/Speedtest/Speedtest.fsproj b/tests/Speedtest/Speedtest.fsproj index bf38f3f6..e31912c5 100644 --- a/tests/Speedtest/Speedtest.fsproj +++ b/tests/Speedtest/Speedtest.fsproj @@ -14,7 +14,7 @@ - + diff --git a/tests/TestUtils/DefaultTestObjects.fs b/tests/TestUtils/DefaultTestObjects.fs index e89b29b0..d76fbf23 100644 --- a/tests/TestUtils/DefaultTestObjects.fs +++ b/tests/TestUtils/DefaultTestObjects.fs @@ -2,11 +2,8 @@ open FsSpreadsheet open Fable.Core -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto + let [] testFolder = "TestFiles" @@ -37,11 +34,13 @@ type TestFiles = type WriteTestFiles = | FsSpreadsheetNET | FsSpreadsheetJS +| FsSpreadsheetPY member this.asFileName = match this with - | FsSpreadsheetNET -> "WRITE_TestWorkbook_FsSpreadsheet.net.xlsx" - | FsSpreadsheetJS -> "WRITE_TestWorkbook_FsSpreadsheet.js.xlsx" + | FsSpreadsheetNET -> "TestWorkbook_FsSpreadsheet_WRITE.net.xlsx" + | FsSpreadsheetJS -> "TestWorkbook_FsSpreadsheet_WRITE.js.xlsx" + | FsSpreadsheetPY -> "TestWorkbook_FsSpreadsheet_WRITE.py.xlsx" member this.asRelativePath = $"{testFolder}/{this.asFileName}" member this.asRelativePathNode = $"./tests/TestUtils/{testFolder}/{this.asFileName}" @@ -118,7 +117,7 @@ module Sheet3 = let defaultTestObject() = let wb = new FsWorkbook() - let table1 = new FsTable(Sheet1.tableName, FsRangeAddress(FsAddress("A1"),FsAddress("F1"))) + let table1 = new FsTable(Sheet1.tableName, FsRangeAddress(FsAddress("A1"),FsAddress("F5"))) let sheet1 = wb.InitWorksheet(Sheet1.sheetName) for row in ExpectedRows.rowCollectionA1 do for c in row do diff --git a/tests/TestUtils/TestUtils.fsproj b/tests/TestUtils/TestUtils.fsproj index 0b4d751e..b3165a25 100644 --- a/tests/TestUtils/TestUtils.fsproj +++ b/tests/TestUtils/TestUtils.fsproj @@ -32,9 +32,7 @@ - - - + @@ -42,7 +40,7 @@ - + diff --git a/tests/TestUtils/TestingUtils.fs b/tests/TestUtils/TestingUtils.fs index 063cf1de..f82457bb 100644 --- a/tests/TestUtils/TestingUtils.fs +++ b/tests/TestUtils/TestingUtils.fs @@ -3,11 +3,8 @@ open FsSpreadsheet open Fable.Core -#if FABLE_COMPILER -open Fable.Mocha -#else -open Expecto -#endif +open Fable.Pyxpecto + [] module Utils = @@ -165,6 +162,13 @@ module Expect = let passWithMsg (message: string) = equal true true message + let fails (f : unit -> unit) message = + try + f() + failwith $"Function should have failed but did not: {message}" + with + | _ -> () + /// Fable compatible Expecto/Mocha unification [] module Test =