Yahtzee in Excel

Posted on February 20, 2019

Download this free Yahtzee game written entirely in Microsoft Excel.

It uses the little-known Excel Camera tool to show pictures of random dice.

Yahtzee screenshot

Great waste of time.

Excel Default Formulas

Posted on February 20, 2019

Developed as a Microsoft Excel add-in, Default Formulas gives the developer the control of protected mode without the limitations.

Establish default formulas for a range.

  • Works great with Tables (ListObjects).
  • Automatically uses structured references if available.

Operator can override default formulas.

  • Default formulas and overriden formulas are designated to the operator by color.
  • Makes changes to formulas obvious.
  • Operator can return cells to their default formulas by simply pressing [Delete].

Use Defaulted and NotDefaulted functions to return ranges of cells for use in calculations.

  • NotDefaulted function makes it simple for default formulas to refer to themselves without encountering circular reference errors.

Create default formulas with circular references.

  • As long as any one of cells in the circular relationship are not defaulted, no errors will result.
  • Very compact method for allowing operator to choose from multiple input methods.
  • Examples:
    • Establish default formulas for Start, Duration, and Finish. Operator can override their choice of any two and the remaining default formula computes the missing value.
    • Establish default formulas for Qty, Unit Price, and Total Price. Operator can override their choice of any two and the remaining default formula computes the missing value.
    • Establish default formulas for Fahrenheit and Celsius. Operator can override their choice and the remaining default formula computes the corresponding value.

Hotkey reveals DefaultFormulas user interface


DefaultFormulas User Interface Screenshot

Default Formulas are stored in hidden named ranges, which can be revealed and edited manually if desired.

Excel Tables in VBA

Posted on February 05, 2019

Extracting data from tables (ListObjects) in Microsoft Excel is very easy within Excel, but within VBA it is rather cumbersome. You can only refer to one column or one row at a time, and there is no way to refer to an individual cell other than by taking an intersection.

The Find method only works on ranges, not tables, so it is cumbersome to search tables because you get trapped dealing with ranges and lose all the benefits of using tables. Also, to find all but the first match, the Find method requires a loop and repeated calls to the FindNext or FindPrevious methods.

I’ve written two excellent functions for dealing with table data in VBA. You can download them here.

TableRange returns a range from a table as the intersection of one or more sections (HeaderRowRange,
DataBodyRange, InsertRowRange, and TotalsRowRange), one or more columns (by name), and/or one or more rows (by numbers). This makes it very simple to address any portion of a table in VBA with a single line of code.

Example: Return all cells in the Client column of the Timeslips table.

tblTimeslips.ListColumns("Client")

– versus –

TableRange(tblTimeslips, "Client")

Example: Return all cells in the Client and Date columns of the Timeslips table.

Union(tblTimeslips.ListColumns("Client"), tblTimeslips.ListColumns("Date"))

– versus –

TableRange(tblTimeslips, Array("Client", "Date"))

Example: Return all cells on row 4 of the Timeslips table.

tblTimeslips.ListRows(4).Range

– versus –

TableRange(tblTimeslips, , 4)

Example: Return all cells on rows 4, 5, and 6 of the Timeslips table.

Union(tblTimeslips.ListRows(4).Range, tblTimeslips.ListRows(5).Range, tblTimeslips.ListRows(6).Range)

– versus –

TableRange(tblTimeslips, , Array(4, 5, 6))

Example: Return cells in Client and Date columns of the Timeslips table from row 4.

Intersect(Union(tblTimeslips.ListColumns("Client"),tblTimeslips.ListColumns("Date")), tblTimeslips.ListRows(4))

– versus –

TableRange(tblTimeslips, Array("Client", "Date"), 4)

TableFind returns a range from a table as the intersection of one or more columns (by name) and any rows matching a specified search value (as formatted) in a specified search column (by name). Compound search criteria can be achieved by taking intersections/unions of multiple TableFind functions.

Example: Return all cells from the Date and Amount columns of the Timeslips table where the corresponding Client column matches "ABC*" and the corresponding Billed column matches "False".

Intersect( _

TableFind(tblTimeslips, "Client", "ABC*", Array("Date", "Amount"), _

TableFind(tblTimeslips, "Billed", "False", Array("Date", "Amount") _

)

Intersect( _

TableFind(tblTimeslips, "Client", "ABC*"), _

TableFind(tblTimeslips, "Billed", "False"), _

TableRange(tblTimeslips, Array("Date", "Amount")) _

)

I’ve also added a clsTable class with interfaces to the TableRange and TableFind
functions, and a Table function for instantiating clsTable objects, thus enabling the abbreviated syntax below:

With Table(tblTimeslips)

Set rng = Intersect( _

.Find("Client", "ABC*"), _

.Find("Billed", "False"), _

.Range(Array("Date", "Amount")) _

)

End With

Excel COLUMN and ROW functions

Posted on January 01, 2019

Using the COLUMN and ROW functions are preferred over the CELL function, because the latter is volatile and will calculate with every change in Excel, even to cells that are not precedents. However, care must be taken to avoid accidentally passing a range of cells, instead of a single cell, to COLUMN and ROW.

If passed a single cell, it returns the column number of the cell.

If passed a range of cells, even if the range is an entire column or row, it returns an array of column or row numbers for each cell in the passed range. This is confusing, and very slow.

If a range is not passed to COLUMN or ROW the range will default to the current cell, which is usually perfect.

Even when a single cell is passed, it is still technically passed as a single-value array, and a single-value array is returned. Although Excel will generally still work as expected, to be explicit would be better, like INDEX(COLUMN(),1), which will return the first value from the array.

Passing Decimal Parameters to SQL Server

Posted on April 09, 2017

' Execute stored procedure to add record.

Set cmd = ADOCommand("InsertLogWaypoint", cn, adCmdStoredProc)

With cmd

.Parameters.Append .CreateParameter("Time", adDBTimeStamp, adParamInput, , rstLog.Fields("Time").Value)

.Parameters.Append .CreateParameter("Lat", adSingle, adParamInput, , rstLog.Fields("Latitude").Value)

.Parameters.Append .CreateParameter("Long", adSingle, adParamInput, , rstLog.Fields("Longitude").Value)

.Parameters.Append .CreateParameter("Acc", adInteger, adParamInput, , rstLog.Fields("Accuracy").Value)

.Parameters.Append .CreateParameter("Dir", adInteger, adParamInput, , rstLog.Fields("Direction").Value)

.Parameters.Append .CreateParameter("Speed", adNumeric, adParamInput, , rstLog.Fields("Speed").Value)

With .Parameters("Speed")

.Precision = 18

.NumericScale = 9

End With

.Parameters.Append .CreateParameter("LocID", adInteger, adParamInput, , rstLog.Fields("LocationID").Value)

.Parameters.Append .CreateParameter("ID", adInteger, adParamOutput)

.Execute

End With