Summary
这个问题在某种程度上是这个问题的后续:
如何从索引实现列自命名? https://stackoverflow.com/questions/5160001/how-to-implement-column-self-naming-from-its-index
测试了上述链接问题的答案中提供的代码后,我终于遇到了严重的性能问题。
性能问题
性能问题发生在工作表初始化时,即当我初始化工作表的单元格时。
''' <summary>
''' Initialize an instance of the Company.Project.Sheet class.
''' </summary>
''' <param name="nativeSheet">The native worksheet from which to initialize.</param>
Friend Sub New(ByVal nativeSheet As Microsoft.Office.Interop.Excel.Worksheet)
_nativeSheet = nativeSheet
Dim cells As IDictionary(Of String, ICell) = New Dictionary(Of String, ICell)()
'These iterations hurt the performance of the API...'
For rowIndex As Integer = 1 To _nativeSheet.Rows.Count Step 1
For colIndex As Integer = 1 To _nativeSheet.Columns.Count Step 1
Dim c As ICell = New Cell(_nativeSheet.Cells(rowIndex, colIndex))
cellules.Add(c.Name, c)
Next
Next
_cellules = New ReadOnlyDictionary(Of String, ICell)(cells)
End Sub
-
ReadOnlyDictionary(TKey、TValue) :
A custom read-only dictionary that simply wraps a IDictionary(Of TKey, TValue) to prevent modifications.
讨论
我之所以这样工作,是因为底层电子表格工作表中的每个单元格都是从工作表初始化到结束(即工作表被处置或最终确定)进行初始化的。因此,我希望以同样的方式初始化工作表的单元格,但我也希望保持使用索引单元格相对于命名(“A1”)单元格的性能提升,同时保持 API 用户的易用性用其名称引用单元格,这就是我打算使用字典的方式,这样当我引用单元格“A1”时,我会将此键访问到我的字典中并相应地寻址单元格 (1, 1)。
除此之外,我知道使用 Worksheet.UsedRange 属性从工作表中读取数据的更快方法,该属性将所有使用的单元格返回到二维矩阵中。
如果无论如何,对于我可以用来初始化 Cell 类的多个实例的单元格集合来说,存在相同或大致相同的单元格,那就太好了,并且性能良好!
我还考虑过在内存中只初始化一个 100 x 100 矩阵单元,同时用我的字典映射它们,因为人们很少会使用整个工作表的单元。因此,我仍在考虑一种必须访问尚未初始化的单元格的方法,例如 Cells(120, 120)。理想情况下,我认为程序必须初始化最大初始初始化 Cell(100, 100) 到 Cell (120, 120) 之间的所有单元格。我在这里说得够清楚了吗?请随时要求澄清! =)
-
另一种选择可能是我只将单元格的名称初始化到字典中并将行和列索引保留在内存中,而不是使用其 nativeCell 初始化 Cell 实例,例如 Range。这是我的 Cell 类的代码来说明我的意思。
'''
''' 代表工作表中的一个单元格。
'''
'''
朋友级细胞
实现 ICell
Private _nativeCell As Microsoft.Office.Interop.Excel.Range
Private _name As String
''' <summary>
''' Initializes a new instance of the Company.Project.Cell class.
''' </summary>
''' <param name="nativeCell">The Microsoft.Office.Interop.Excel.Range to wrap.</param>
Friend Sub New(ByVal nativeCell As Microsoft.Office.Interop.Excel.Range)
_nativeCell = nativeCell
End Sub
Public ReadOnly Property NativeCell() As Microsoft.Office.Interop.Excel.Range Implements ICellule.NativeCell
Get
Return _nativeCell
End Get
End Property
Public ReadOnly Property Column() As Integer Implements ICell.Column
Get
Return _nativeCell.Column
End Get
End Property
Public ReadOnly Property Row() As Integer Implements ICell.Row
Get
Return _nativeCell.Row
End Get
End Property
Public ReadOnly Property Name() As String Implements ICellule.Name
Get
If (String.IsNullOrEmpty(_name) OrElse _name.Trim().Length = 0) Then _
_name = GetColumnName()
Return _nom
End Get
End Property
Public Property Value() As Object Implements ICellule.Value
Get
Return _nativeCell.Value2
End Get
Set(ByVal value As Object)
_nativeCell.Value2 = value
End Set
End Property
Public ReadOnly Property FormattedValue() As String Implements ICellule.FormattedValue
Get
Return _nativeCell.Text
End Get
End Property
Public ReadOnly Property NumericValue() As Double? Implements ICellule.NumericValue
Get
Return Value
End Get
End Property
问题
我还有哪些其他选择?
还有其他方法可以穿越吗?
对于性能问题,有没有一种方法可以使实际方法可行?
供您参考,此问题在测试中超时,因此测试从未在可接受的时间范围内结束,而这实际上需要几个世纪的时间......
欢迎任何想法!我对其他解决方案或方法持开放态度,这些解决方案或方法将帮助我在解决此性能问题的同时实现此目标。
谢谢大家! =)
EDIT #1
谢谢马克西姆·格万多夫 https://stackoverflow.com/users/574995/maxim-gueivandov,他的解决方案解决了我在这个问题中提到的问题。
除此之外,这个解决方案还带来了另一个问题:SystemOutOfMemoryException
,这将在另一个问题中解决。
我最诚挚地感谢马克西姆·格万多夫。