Due to some recent activity in the playing of this game, I started to think about any enhancements that would make the game easier to play. I realized that if a column was added to the scoring that showed the number of hits on each individual sheet for each cube, it would provide additional information to the player. So, my goal was to add that column, as shown in the figure below.
Initially, I thought that this would be a relatively simple task. However, I was wrong. The cube ships are laid out randomly as 3-D ranges. It is difficult or impossible to return the 2-D range associated with the 3-D range with normal worksheet formulas due to the limited ways to operate on 3-D ranges with worksheet functions. Thus, I realized that a UDF would be needed, since I did not want to modify the original programming. Then, I determined that the information that the UDF would require is:
- The 3-D range reference string.
- The “number” of the cube.
- The position(s) of the desired information in a 3-D range reference string.
- The first and last sheet of the 3-D range.
- The 2-D range associated with the 3-D range.
- The sheetname where it is being called from.
The complete code for the UDF is shown below.
Function SumSheetsHits()
Application.Volatile True
sRangeRaw = ThisWorkbook.Names(“cShip” & Application.Caller.Row – 5).RefersTo
sExclamation = Application.Find(“!”, sRangeRaw)
sColon = Application.Find(“:”, sRangeRaw)
sTick = InStr(sColon, sRangeRaw, “‘”)
If sColon = 4 Then
iFirst = Val(Mid(sRangeRaw, 3, 1))
Else
iFirst = Val(Mid(sRangeRaw, 3, 2))
End If
If sTick – sColon = 2 Then
iSecond = Val(Mid(sRangeRaw, sColon + 1, 1))
Else
iSecond = Val(Mid(sRangeRaw, sColon + 1, 2))
End If
aSheetNum = Val(ActiveSheet.Name)
srange = Mid(sRangeRaw, Application.Find(“!”, sRangeRaw) + 1, 255)
If aSheetNum < iFirst Or aSheetNum > iSecond Then
Else
SumSheetsHits = Application.Sum(ActiveSheet.Range(srange))
End If
End Function
So, the function =SumSheetsHits() is entered in column Y beginning on row 6. The line of code ThisWorkbook.Names(“cShip” & Application.Caller.Row – 5).RefersTo returns the 3-D formula string for cube 1 when entered in Y6. Application.Caller.Row is in row 6 in this example, so ThisWorkbook.Names(“cShip” & 6 – 5).RefersTo cShip1 and returns “ =’6:8’!$B$5:$D$7 “ which is the 3x3x3 cube 3-D reference.
Next, the 3 important characters for finding the desired information in the string are located. Note that both the FIND function and the InStr function are to find those positions, but really the InStr function could have been used for all 3 lookups.
sExclamation = Application.Find(“!”, sRangeRaw)
sColon = Application.Find(“:”, sRangeRaw)
sTick = InStr(sColon, sRangeRaw, “‘”)
The variable sTick shows the location of the 2nd tick in the string, since the search is made after the colon.
In order to find the first sheetname in the string (which by definition is a 1 or 2 digit number), this simple if, End if logic block of code is used.
If sColon = 4 Then
iFirst = Val(Mid(sRangeRaw, 3, 1))
Else
iFirst = Val(Mid(sRangeRaw, 3, 2))
End If
Note the use of the Val function, which converts the numeric string to an actual number. The find the second sheetname, the difference of sTick and sColon are used to define whether a 1 or 2 digit number is used.
If sTick – sColon = 2 Then
iSecond = Val(Mid(sRangeRaw, sColon + 1, 1))
Else
iSecond = Val(Mid(sRangeRaw, sColon + 1, 2))
End If
The sheetname is returned by the following code.
aSheetNum = Val(ActiveSheet.Name)
Since (fortuitously) the sheet names are consecutive numbers, that information makes the job of bounding the 3-D range much easier.
The 2-D range part of the formula is:
srange = Mid(sRangeRaw, Application.Find(“!”, sRangeRaw) + 1, 255)
and it is used with the final block of code.
If aSheetNum < iFirst Or aSheetNum > iSecond Then
Else
SumSheetsHits = Application.Sum(ActiveSheet.Range(srange))
End If
Since the 3-D range is bounded by these 2 sheets, any sheets outside would not be capable of recording any hits on this ship.
You might question the use of the SUM function here, when a hit on a ship appears as an “X”. Actually, when a shot is made, a 1 is placed in the cell, and the appearance of the “X” occurs through custom fomatting.
xlCubeSuper is now available with this new game functionaity, and can be downloaded by clicking the following link.