fsprojects / ExcelProvider

This library is for the .NET platform implementing a Excel type provider.
http://fsprojects.github.io/ExcelProvider/
The Unlicense
141 stars 51 forks source link

Running from an F# script within Visual Studio using relative paths #79

Closed jonsagara closed 3 years ago

jonsagara commented 3 years ago

Description

This is more a question on proper usage; I think ExcelProvider is behaving correctly.

I'm trying to load a spreadsheet at runtime in a .fsx file from FSI within Visual Studio. The .xlsx file resides in the same directory as the .fsx file. ExcelProvider is satisfied by the relative path, but when I execute the script, I get a FileNotFoundException:

InventoryPriceUpdate.fsx(12,24): error FS3033: The type provider 'FSharp.Interop.Excel.ExcelProvider.ProviderImplementation+ExcelProvider' reported an error: Could not open file 'C:\Users\Jon\AppData\Local\Temp\nuget\1932--71a8b809-102e-4160-8619-47f88b5e57f3\Inventory.xlsx'. FileNotFoundException - Could not find file 'C:\Users\Jon\AppData\Local\Temp\nuget\1932--71a8b809-102e-4160-8619-47f88b5e57f3\Inventory.xlsx'.

Here is the script:

#r "nuget: ExcelProvider"

open FSharp.Interop.Excel

type InventoryPrices = ExcelFile<"Inventory.xlsx">

At runtime, ExcelProvider is looking for my file in the directory C:\Users\Jon\AppData\Local\Temp\nuget\1932--71a8b809-102e-4160-8619-47f88b5e57f3\Inventory.xlsx, which of course is different than my development directory where I'm editing the .fsx file.

How do I get ExcelProvider to load the spreadsheet at runtime without hard coding the path to the spreadsheet?

Repro steps

  1. In Visual Studio, create an .fsx file
  2. Add an .xlsx file to the same directory as the .fsx file
  3. Set up ExcelProvider as demonstrated above
  4. Run the .fsx file in F# Interactive within Visual Studio (I highlighted all the text and presset ALT+ENTER on my keyboard)

Expected behavior

I think this is working correctly because I don't expect the script to know about files and copy them to the correct location.

Actual behavior

ExcelProvider can't find the spreadsheet because it is executing from a different temp directory.

Known workarounds

If I hard code the path to the .xlsx file, everything works. However, I'd like to avoid having a hard coded path, if possible.

Related information

Thank you,

Jon

sergey-tihon commented 3 years ago

I think that the good practice is to use __SOURCE_DIRECTORY__. This is reliably way to be sure that path is correct.

#r "nuget: ExcelProvider"

open FSharp.Interop.Excel

let [<Literal>] File = __SOURCE_DIRECTORY__ + "/Inventory.xlsx"
type InventoryPrices = ExcelFile<File>

but you also can contribute a fix 😝 here https://github.com/fsprojects/ExcelProvider/blob/master/src/ExcelProvider.DesignTime/ExcelProvider.DesignTime.fs#L149 cfg:TypeProviderConfig come with cfg.ResolutionFolder that should be used as root folder if filename is not absolute

        // Resolve the filename relative to the resolution folder.
        let resolvedFilename = Path.Combine(cfg.ResolutionFolder, filename)
jonsagara commented 3 years ago

That worked perfectly. Thank you!

jonsagara commented 3 years ago

A little followup: looks like this is a known issue:

https://github.com/dotnet/fsharp/issues/10865