Summary
This question is the follow-up of a a desire to architect a simple spreadsheet API while keeping it user-friendly to those who know Excel well.
To sum it up, this question is related to these below two:
1. How to implement column self-naming from its index?;
2. How to make this custom worksheet initialization faster?.
Objective
To provide a simplified Excel API used as a wrapper over the nevralgic components such as the Application
, the Workbook
, the Worksheet
and the Range
classes/interfaces while exposing only the most commonly used object properties for each of these.
Usage example
This usage example is inspired from the unit tests that allowed me to bring this solution up to where it stands now.
Dim file as String = "C:\Temp\WriteTest.xls"
Using mgr As ISpreadsheetManager = New SpreadsheetManager()
Dim wb as IWorkbook = mgr.CreateWorkbook()
wb.Sheets("Sheet1").Cells("A1").Value = 3.1415926
wb.SaveAs(file)
End Using
And now we open it:
Dim file as String = "C:\Temp\WriteTest.xls"
Using mgr As ISpreadsheetManager = New SpreadsheetManager()
Dim wb as IWorkbook = mgr.OpenWorkbook(file)
// Working with workbook here...
End Using
Discussion
While instantiating an Excel Workbook:
- An instance of a Worksheet is automatically initialized in the Workbook.Sheets collection;
- Upon initialization, a Worksheet initializes its Cells through the
Range
object that can represent one or multiple cells.
These Cells are immediately accessible with all their properties as soon as the Worksheet exists.
My wish is to reproduce this behaviour so that
- The Workbook class constructor initializes the Workbook.Sheets collection property with the native sheets;
- The Worksheet class constructor initializes the Worksheet.Cells collection property with the native cells.
My problem comes from the Worksheet class constructor while initializing the Worksheet.Cells collection property illustrated at #2.
Thoughts
Following these above-linked questions encountered issues, I wish to figure out another architecture that would allow me to:
- Access specific feature of a cell
Range
when required; - Deliver most commonly used properties through my
ICell
interface; - Having access to all of the
Range
cells of a worksheet from its initialization.
While keeping in mind that accessing a Range.Value
property is the fastest interaction possible with the underlying Excel application instance using the Interop.
So, I thought of initializing my ReadonlyOnlyDictionary(Of String, ICell)
with the name of the cells without immediately wrapping an instance of the Range
interface so that I would simply generate the row and column indexes along with the cell's name to index my dictionary, then, assigning the Cell.NativeCell
property only when one wants to access or format a specific cell or cell range.
That way, the data in the dictionary would be indexed with the name of the cells obtained from the column indexes generated in the Worksheet
class constructor. Then, when one would do this:
Using mgr As ISpreadsheetManager = New SpreadsheetManager()
Dim wb As IWorkbook = mgr.CreateWorkbook()
wb.Sheet(1).Cells("A1").Value = 3.1415926 // #1:
End Using
#1: This would allow me to use the indexes from my Cell
class to write the given value to the specific cell, which is faster then using its name directly against the Range
.
Questions and Concerns
Besides, when working with UsedRange.get_Value()
or Cells.get_Value()
, this returns Object(,) arrays.
1. So should I just be happy with working with Object(,)
arrays for cells, without having the possibility to format it somehow?
2. How to architect these Worksheet and Cell classes so that I have the best performance offered while working with Object(,)
arrays, while keeping the possibility that a Cell instance may represent or wrap a single cell Range?
Thanks to any of you who takes the time to read my post and my sincerest thanks to those who answer.