If you use FCell embedded F#/C#/VB.NET code editor then by default FCell will save the source code in the workbook as Custom XML.

You can extend the functionality and implement your own source code manager, e.g. integrate with a source code repository.

The extension uses MEF as the underlying technology. Users only need to implement a simple interface as shown below.

Implement a custom MEF component for FCell source code manager

The component is simply an assembly with exactly 1 class which implements ISourceCodeManager (defined in FCell.ManagedXll). This interface has only 2 methods:

  • LoadSourceCode(wbk : Workbook, lang : SourceCodeLanguage) which should return source code for given language as a string. You get a reference to ActiveWorkbook so that you can store and read some data from the workbook Custom xml, e.g. path to source code file, login to source code repository etc. This method is called when you open an embedded FCell code editor.

  • SaveSourceCode(wbk : Workbook, lang : SourceCodeLanguage, code : string)) is called when you save a workbook with open FCell code editor. You get a reference to the ActiveWorkbook so that you can use its Custom xml and read some data e.g. path to file where source code should be saved.

The code example below shows a simple implementation:

Note

You can create FCell Ribbon or Custom Task Pane UI to manipulate workbook Custom XML

F# Copy imageCopy
open System
open FCell.ManagedXll
open System.IO
open Microsoft.Office.Interop.Excel
open System.ComponentModel.Composition
open System.Xml
open System.Text

[<Export(typeof<ISourceCodeManager>)>]
type SourceCodeManager() =

    //this function will search workbook custom xml parts for xml with element "SourceCodeLocation"
    //it is assumed that if such part exists it stores the path to source code file in its inner text
    let getSourceLocation(wbk : Workbook) =
        let xmlKey = "SourceCodeLocation"
        let xmlParts = wbk.CustomXMLParts
        let count = xmlParts.Count
        match [|1..count|] |> Array.tryFind (fun i -> let part = xmlParts.[i]
                                                      part.XML.Contains(xmlKey)) with
            | Some(i) -> 
                let xmlDoc = new XmlDocument()
                xmlDoc.LoadXml(xmlParts.[i].XML)
                UTF8Encoding.UTF8.GetString(Convert.FromBase64String(xmlDoc.InnerText))
            | _ -> ""

    interface ISourceCodeManager with

        member this.LoadSourceCode(wbk : Workbook, lang : SourceCodeLanguage) = 
            //assume path to source code file is saved in workbook custom xml
            let sourceCodeLocation = getSourceLocation(wbk)

            //if file exists then read its contents and return
            if File.Exists(sourceCodeLocation) then
                File.ReadAllText(sourceCodeLocation)
            else ""

        member this.SaveSourceCode(wbk : Workbook, lang : SourceCodeLanguage, code : string) = 
            //assume path to source code file is saved in workbook custom xml
            let sourceCodeLocation = getSourceLocation(wbk)

            //if file exists then save code from open code editor in that location
            if File.Exists(sourceCodeLocation) then
                File.WriteAllText(sourceCodeLocation, code)

Plug in SourceCodeManager extension into FCell

This extension can only be used with full FCell installation because it needs FCell embedded code editors. Simply save the extension assembly in %FCell folder%/Extensions and restart Excel.