Author Archives: Rolf

F# DynamicOracleDataReader

Dynamic reading from an Oracle database

Implementation

let inline tryUnbox<'a> (x:obj) =
    match x with
    | :? 'a as result -> Some(result)
    | _ -> None

type DynamicOracleDataReader(reader:OracleDataReader) =
    member private x.Reader = reader
    member x.Read() = reader.Read()
    static member (?) (dr:DynamicOracleDataReader, name:string) : 'a option = 
        tryUnbox (dr.Reader.[name])
    interface IDisposable with
        member x.Dispose() = reader.Dispose()

type DynamicOracleCommand(cmd:OracleCommand) =
    member private x.Command = cmd
    static member (?<-) (cmd:DynamicOracleCommand, name:string, value) = 
        let p = new OracleParameter(name, box value) 
        cmd.Command.Parameters.Add(p) |> ignore
    member x.ExecuteNonQuery() = cmd.ExecuteNonQuery()
    member x.ExecuteReader() = new DynamicOracleDataReader(cmd.ExecuteReader())
    member x.ExecuteScalar() = cmd.ExecuteScalar()
    member x.Parameters = cmd.Parameters
    interface IDisposable with
        member x.Dispose() = cmd.Dispose()

type DynamicOracleConnection(connStr:string) =
    let conn = new OracleConnection(connStr)
    member private x.Connection = conn
//    static member (?) (conn:DynamicOracleConnection, name) =
//        let command = new OracleCommand(name, conn.Connection)
//        command.CommandType <- CommandType.Text 
//        new DynamicOracleCommand(command)
    member x.GenerateCommand(query:string) = 
        let command = new OracleCommand(query, conn)
        command.BindByName <- true
        new DynamicOracleCommand(command)
    member x.Open() = conn.Open()

    interface IDisposable with
        member x.Dispose() = conn.Dispose()

Usage

type Order = {
    OrderId: int
    Comments: string option}

let connectionString = 
    "User Id = XXXXXX; " + 
    "Password = XXXXXX; " + 
    "Data Source = " + 
        "(Description = " +
        "(Address = " + 
        "(Protocol = TCP) " + 
        "(Host = 127.0.0.1) " + 
        "(Port = 1521)) " + 
        "(Connect_Data = (Service_Name = XXXXXX)))"

let getOrderByIdQuery =
    "select * " +
    "from ORDERS " +
    "where IDORDER = : orderId " +
    "order by IDORDER"

let getOrderById (orderId: int) = seq {
    use conn = new DynamicOracleConnection(connectionString)
    use cmd = conn.GenerateCommand(getOrderByIdQuery)
    
    cmd?orderId <- orderId

    conn.Open()
    use reader = cmd.ExecuteReader ()

    while (reader.Read()) do
        yield {
            OrderId = defaultArg reader?IDORDER 0
            Comments = reader?COMMENTS}}

References

F# applications with icons

Icons of an F# WPF application

There are at least two different usages for icons. First, there is the application icon displayd on the top left corner of the application window and also in the task bar. Second, Windows Explorer shows application icons in the file lists and also uses them for shortcuts.

Application icon

  1. Create the icon. For example, save an image with Paint as a 256 color bitmap and change the file extension to *.ico
  2. Save the icon in an “Resources” subfolder of the project
  3. Set the Build Action of the icon to Resource
  4. Include the icon with the XAML file
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Icon="/Resources/MyIcon.ico"
        Title="MyApplication" Height="600" Width="1000" >

Windows Explorer icon

  1. Save the icon in 3.00 format using the free tool @icon sushi.
  2. Create a text file with a *.rc extension. Save the *.rc file in the “Resources” subfolder.
  3. The *.rc file should contain a single line. The ‘1’ is part of the text and not a line number.
1 ICON "MyIcon.ico"
  1. Ensure that the Resource Compiler rc.exe is installed. Adding the C++ Tools to Visual Studio should also install rc.exe.
  2. Compile the *.rc file with rc.exe into an *.res file.
C:\Program Files (x86)\Windows Kits\10\bin\x86>rc.exe /v C:\pathToMyFile\Resources\MyResources.rc
C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86>rc.exe /v "C:\pathToMyFile\Resources\MyResources.rc"
  1. In Visual Studio, select the Application tab of project property page
  2. Select the compiled *.res file in the Resources section. The complete absolute path to the file is shown. Leave the tick box “Use standard resource names” unchecked.
  3. With a text editor edit the project *.fsproj file. Change the absolut path to a relative path.
    Visual Studio should be closed.
<Win32Resource>Resources\MyResources.res</Win32Resource>

Windows Explorer Icon with .NET 5

Adding a Windows Explorer Icon became lot simpler with .NET 5:

  1. Get an icon: Create an icon from a image as outline above or download it from https://icon-icons.com or https://iconarchive.com
  2. Copy the icon to a Resources folder in the project folder
    Resources/MyIcon.ico
  3. Edit the project file *.fsproj. Add the <ApplicationIcon> tag:
&lt;Project Sdk="Microsoft.NET.Sdk">

  &lt;PropertyGroup>
    &lt;OutputType>WinExe&lt;/OutputType>
    &lt;TargetFramework>net5.0-windows&lt;/TargetFramework>
    ...
	&lt;ApplicationIcon>Resources/FillCertificate.ico&lt;/ApplicationIcon>
  &lt;/PropertyGroup>

References

F# and Excel

Add a reference to the solution:
Project menu > Add Reference. On the COM tab, locate Microsoft Excel 16.0 Object Library. That’s the reference which contains Microsoft.Office.Interop.Excel.dll.
Also, add a reference to the office library Microsoft Office 16.0 Object Library.

#if INTERACTIVE
#r "Microsoft.Office.Interop.Excel"
#endif

open System
open Microsoft.Office.Interop.Excel

let excel = new ApplicationClass(Visible = false)
let workbook = excel.Workbooks.Open (templateFile)
//let workbook = excel.Workbooks.Add (xlWBATemplate.xlWBATWorksheet)
let worksheet = (workbook.Worksheets.[1] :?> Worksheet)

excel.Visible <- true
excel.Application.ScreenUpdating <- false

worksheet.Range("A9","E9").Value2 <- [| "This"; "is"; "my"; "test"; ":-)" |]

workbook.SaveAs(outputFile)

workbook.Close()
excel.Workbooks.Close()
excel.Application.Quit()

releaseObject excel

VBA 96 well plates positions

Function IsValidPosition(position As Integer) As Boolean
    If 1 <= position And position <= 96 Then
        IsValidPosition = True
    Else
        IsValidPosition = False
    End If
End Function


Function GetCoordinateFromVerticalPosition _
            (verticalPosition As Integer) As String
    Dim row As Integer
    Dim rowString As String
    Dim column As Integer
    Dim returnValue As String
        
    rowString = "A"
    
    If IsValidPosition(verticalPosition) Then
        row = (verticalPosition - 1) Mod 8 + 1
        rowString = Chr(Asc(rowString) + row - 1)
        column = (verticalPosition - row) / 8 + 1
        returnValue = rowString & column
    Else
        MsgBox "Invalid position number." & _
                vbNewLine & vbNewLine & _
                "Allowed values are 1-96.", _
                vbCritical, "GetCoordinateFromVerticalPosition: Invalid input"
        returnValue = vbNullString
    End If
    GetCoordinateFromVerticalPosition = returnValue
End Function